boot: merge retooled EFI loader
This commit is contained in:
parent
c66f39a563
commit
1a44f8a2f3
33
Makefile
33
Makefile
@ -169,6 +169,7 @@ clean:
|
||||
-rm -f $(LIBC_OBJS) $(BASE)/lib/ld.so $(BASE)/lib/libkuroko.so $(BASE)/lib/libm.so
|
||||
-rm -f $(BASE)/bin/kuroko
|
||||
-rm -f $(GCC_SHARED) $(LIBSTDCXX)
|
||||
-rm -f boot/efi/*.o boot/bios/*.o
|
||||
|
||||
libc/%.o: libc/%.c base/usr/include/syscall.h
|
||||
$(CC) -O2 -std=gnu11 -Wall -Wextra -Wno-unused-parameter -fPIC -c -o $@ $<
|
||||
@ -214,13 +215,17 @@ $(BASE)/usr/lib:
|
||||
mkdir -p $@
|
||||
$(BASE)/usr/bin:
|
||||
mkdir -p $@
|
||||
boot/efi:
|
||||
mkdir -p $@
|
||||
boot/bios:
|
||||
mkdir -p $@
|
||||
fatbase/efi/boot:
|
||||
mkdir -p $@
|
||||
cdrom:
|
||||
mkdir -p $@
|
||||
.make:
|
||||
mkdir -p .make
|
||||
dirs: $(BASE)/dev $(BASE)/tmp $(BASE)/proc $(BASE)/bin $(BASE)/lib $(BASE)/cdrom $(BASE)/usr/lib $(BASE)/usr/bin $(BASE)/lib/kuroko cdrom $(BASE)/var fatbase/efi/boot .make $(BASE)/mod
|
||||
dirs: $(BASE)/dev $(BASE)/tmp $(BASE)/proc $(BASE)/bin $(BASE)/lib $(BASE)/cdrom $(BASE)/usr/lib $(BASE)/usr/bin $(BASE)/lib/kuroko cdrom $(BASE)/var fatbase/efi/boot .make $(BASE)/mod boot/efi boot/bios
|
||||
|
||||
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
|
||||
-include ${APPS_Y}
|
||||
@ -274,18 +279,32 @@ fatbase/kernel: misaka-kernel
|
||||
cp $< $@
|
||||
strip $@
|
||||
|
||||
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel util/mkdisk.sh | dirs
|
||||
cdrom/fat.img: fatbase/ramdisk.igz fatbase/kernel fatbase/efi/boot/bootx64.efi util/mkdisk.sh | dirs
|
||||
util/mkdisk.sh $@ fatbase
|
||||
|
||||
cdrom/boot.sys: boot/boot.o $(patsubst %.c,%.o,$(wildcard boot/*.c)) boot/link.ld | dirs
|
||||
${LD} -melf_i386 -T boot/link.ld -o $@ boot/boot.o $(patsubst %.c,%.o,$(wildcard boot/*.c))
|
||||
cdrom/boot.sys: boot/bios/boot.o $(patsubst boot/%.c,boot/bios/%.o,$(wildcard boot/*.c)) boot/link.ld | dirs
|
||||
${LD} -melf_i386 -T boot/link.ld -o $@ boot/bios/boot.o $(patsubst boot/%.c,boot/bios/%.o,$(wildcard boot/*.c))
|
||||
|
||||
boot/%.o: boot/%.c boot/*.h
|
||||
${CC} -m32 -c -Os -fno-strict-aliasing -finline-functions -ffreestanding -mgeneral-regs-only -o $@ $<
|
||||
boot/bios/%.o: boot/%.c boot/*.h | dirs
|
||||
${CC} -m32 -c -Os -fno-pic -fno-pie -fno-strict-aliasing -finline-functions -ffreestanding -mgeneral-regs-only -o $@ $<
|
||||
|
||||
boot/boot.o: boot/boot.S
|
||||
boot/bios/boot.o: boot/boot.S | dirs
|
||||
${AS} --32 -o $@ $<
|
||||
|
||||
EFI_CFLAGS=-fno-stack-protector -fpic -DEFI_PLATFORM -ffreestanding -fshort-wchar -I /usr/include/efi -mno-red-zone
|
||||
EFI_SECTIONS=-j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .reloc
|
||||
EFI_LINK=/usr/lib/crt0-efi-x86_64.o -nostdlib -znocombreloc -T /usr/lib/elf_x86_64_efi.lds -shared -Bsymbolic -L /usr/lib -lefi -lgnuefi
|
||||
|
||||
boot/efi/%.o: boot/%.c boot/*.h | dirs
|
||||
$(CC) ${EFI_CFLAGS} -I /usr/include/efi/x86_64 -DEFI_FUNCTION_WRAPPER -c -o $@ $<
|
||||
|
||||
boot/efi64.so: $(patsubst boot/%.c,boot/efi/%.o,$(wildcard boot/*.c)) boot/*.h
|
||||
$(LD) $(patsubst boot/%.c,boot/efi/%.o,$(wildcard boot/*.c)) ${EFI_LINK} -o $@
|
||||
|
||||
fatbase/efi/boot/bootx64.efi: boot/efi64.so
|
||||
mkdir -p fatbase/efi/boot
|
||||
objcopy ${EFI_SECTIONS} --target=efi-app-x86_64 $< $@
|
||||
|
||||
image.iso: cdrom/fat.img cdrom/boot.sys util/update-extents.py
|
||||
xorriso -as mkisofs -R -J -c bootcat \
|
||||
-b boot.sys -no-emul-boot -boot-load-size full \
|
||||
|
@ -165,8 +165,8 @@ done:
|
||||
|
||||
cli
|
||||
|
||||
.global kmain
|
||||
ljmp $0x08,$kmain
|
||||
.global bios_main
|
||||
ljmp $0x08,$bios_main
|
||||
|
||||
hang:
|
||||
jmp hang
|
||||
|
@ -10,7 +10,12 @@
|
||||
|
||||
/* Basic text strings */
|
||||
#define BASE_VERSION "ToaruOS Bootloader v4.0"
|
||||
char * VERSION_TEXT = BASE_VERSION " (BIOS)";
|
||||
char * VERSION_TEXT = BASE_VERSION
|
||||
#ifdef EFI_PLATFORM
|
||||
" (EFI)";
|
||||
#else
|
||||
" (BIOS)";
|
||||
#endif
|
||||
char * HELP_TEXT = "<Enter> to boot, <e> to edit, or select a menu option with \030/\031/\032/\033.";
|
||||
char * HELP_TEXT_OPT = "<Enter> to toggle, or select another option with \030/\031/\032/\033.";
|
||||
char * COPYRIGHT_TEXT = "ToaruOS is free software under the NCSA license.";
|
||||
@ -22,7 +27,6 @@ char * LINK_TEXT = "https://toaruos.org - https://github.com/klange/toaruos";
|
||||
#define DEFAULT_SINGLE_CMDLINE "start=terminal\037-F "
|
||||
#define DEFAULT_TEXT_CMDLINE "start=--vga vid=text "
|
||||
#define DEFAULT_VID_CMDLINE "vid=auto,1440,900 "
|
||||
#define DEFAULT_PRESET_VID_CMDLINE "vid=preset "
|
||||
#define MIGRATE_CMDLINE "migrate "
|
||||
#define DEFAULT_HEADLESS_CMDLINE "start=--headless "
|
||||
|
||||
@ -33,18 +37,19 @@ char cmdline[1024] = {0};
|
||||
/* Names of the available boot modes. */
|
||||
struct bootmode boot_mode_names[] = {
|
||||
{1, "normal", "Normal Boot"},
|
||||
#ifdef EFI_PLATFORM
|
||||
{2, "video", "Configure Video Output"},
|
||||
#else
|
||||
{2, "vga", "VGA Text Mode"},
|
||||
#endif
|
||||
{3, "single", "Single-User Graphical Terminal"},
|
||||
{4, "headless", "Headless"},
|
||||
};
|
||||
|
||||
int base_sel = BASE_SEL;
|
||||
|
||||
extern char _bss_start[];
|
||||
extern char _bss_end[];
|
||||
int base_sel = 0;
|
||||
|
||||
int kmain() {
|
||||
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
|
||||
BOOT_SET();
|
||||
|
||||
BOOT_OPTION(_debug, 0, "Debug output",
|
||||
"Enable debug output in the bootloader and enable the",
|
||||
@ -86,6 +91,16 @@ int kmain() {
|
||||
/* Loop over rendering the menu */
|
||||
show_menu();
|
||||
|
||||
#ifdef EFI_PLATFORM
|
||||
if (boot_mode == 2) {
|
||||
extern int video_menu(void);
|
||||
video_menu();
|
||||
boot_edit = 0;
|
||||
memset(cmdline, 0, 1024);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build our command line. */
|
||||
strcat(cmdline, DEFAULT_ROOT_CMDLINE);
|
||||
|
||||
|
@ -1,49 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include "iso9660.h"
|
||||
#include "util.h"
|
||||
#include "text.h"
|
||||
|
||||
iso_9660_volume_descriptor_t * root = NULL;
|
||||
iso_9660_directory_entry_t * dir_entry = NULL;
|
||||
static char * dir_entries = NULL;
|
||||
|
||||
int navigate(char * name) {
|
||||
dir_entry = (iso_9660_directory_entry_t*)&root->root;
|
||||
dir_entries = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
|
||||
long offset = 0;
|
||||
while (1) {
|
||||
iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset);
|
||||
if (dir->length == 0) {
|
||||
if (offset < dir_entry->extent_length_LSB) {
|
||||
offset += 1; // this->block_size - ((uintptr_t)offset % this->block_size);
|
||||
goto try_again;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!(dir->flags & FLAG_HIDDEN)) {
|
||||
char file_name[dir->name_len + 1];
|
||||
memcpy(file_name, dir->name, dir->name_len);
|
||||
file_name[dir->name_len] = 0;
|
||||
char * s = strchr(file_name,';');
|
||||
if (s) {
|
||||
*s = '\0';
|
||||
}
|
||||
#if 1
|
||||
print("Found a file: ");
|
||||
print(" Name: ");
|
||||
print(file_name); print("\n");
|
||||
#endif
|
||||
if (!strcmp(file_name, name)) {
|
||||
dir_entry = dir;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
offset += dir->length;
|
||||
try_again:
|
||||
if ((long)(offset) > dir_entry->extent_length_LSB) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
83
boot/kbd.c
83
boot/kbd.c
@ -1,5 +1,87 @@
|
||||
#include "kbd.h"
|
||||
#include "util.h"
|
||||
#include "text.h"
|
||||
|
||||
#ifdef EFI_PLATFORM
|
||||
#include <efi.h>
|
||||
extern EFI_SYSTEM_TABLE *ST;
|
||||
|
||||
#define KBD_SCAN_DOWN 0x50
|
||||
#define KBD_SCAN_UP 0x48
|
||||
#define KBD_SCAN_LEFT 0x4B
|
||||
#define KBD_SCAN_RIGHT 0x4D
|
||||
#define KBD_SCAN_ENTER 0x1C
|
||||
#define KBD_SCAN_1 2
|
||||
#define KBD_SCAN_9 10
|
||||
|
||||
int read_scancode(int timeout) {
|
||||
EFI_INPUT_KEY Key;
|
||||
unsigned long int index;
|
||||
if (timeout) {
|
||||
EFI_EVENT events[] = {ST->ConIn->WaitForKey, 0};
|
||||
uefi_call_wrapper(ST->BootServices->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &events[1]);
|
||||
uefi_call_wrapper(ST->BootServices->SetTimer, 3, events[1], TimerRelative, 10000000UL);
|
||||
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 2, events, &index);
|
||||
} else {
|
||||
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
|
||||
}
|
||||
EFI_STATUS result = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
|
||||
|
||||
if (result == EFI_NOT_READY) return -1;
|
||||
switch (Key.ScanCode) {
|
||||
case 0:
|
||||
switch (Key.UnicodeChar) {
|
||||
case L'\r':
|
||||
return KBD_SCAN_ENTER;
|
||||
case L'1':
|
||||
case L'2':
|
||||
case L'3':
|
||||
case L'4':
|
||||
case L'5':
|
||||
case L'6':
|
||||
case L'7':
|
||||
case L'8':
|
||||
case L'9':
|
||||
return Key.UnicodeChar - L'1' + KBD_SCAN_1;
|
||||
case L'e':
|
||||
return 0x12;
|
||||
default:
|
||||
return 0xFF;
|
||||
}
|
||||
break;
|
||||
case 0x01: return KBD_SCAN_UP;
|
||||
case 0x02: return KBD_SCAN_DOWN;
|
||||
case 0x03: return KBD_SCAN_RIGHT;
|
||||
case 0x04: return KBD_SCAN_LEFT;
|
||||
default:
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
int read_key(char * c) {
|
||||
EFI_INPUT_KEY Key;
|
||||
unsigned long int index;
|
||||
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
|
||||
uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
|
||||
|
||||
if (Key.ScanCode == 0) {
|
||||
*c = Key.UnicodeChar;
|
||||
if (*c == '\r') *c = '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (Key.ScanCode) {
|
||||
case 0x03: return 3;
|
||||
case 0x04: return 2;
|
||||
case 0x09: return 4;
|
||||
case 0x0a: return 5;
|
||||
case 0x17: *c = 27; return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int read_cmos_seconds(void) {
|
||||
outportb(0x70,0);
|
||||
@ -70,3 +152,4 @@ int read_scancode(int timeout) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
12
boot/menu.c
12
boot/menu.c
@ -42,18 +42,6 @@ void show_menu(void) {
|
||||
sel_max++;
|
||||
}
|
||||
sel_max += base_sel + 1;
|
||||
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, 0xFF);
|
||||
outportb(0x3D4, 15);
|
||||
outportb(0x3D5, 0xFF);
|
||||
|
||||
inportb(0x3DA);
|
||||
outportb(0x3C0, 0x30);
|
||||
char b = inportb(0x3C1);
|
||||
b &= ~8;
|
||||
outportb(0x3c0, b);
|
||||
|
||||
clear_();
|
||||
|
||||
do {
|
||||
|
469
boot/multiboot.c
469
boot/multiboot.c
@ -7,6 +7,7 @@
|
||||
#include "elf.h"
|
||||
#include "options.h"
|
||||
#include "iso9660.h"
|
||||
#include "kbd.h"
|
||||
|
||||
char * kernel_load_start = 0;
|
||||
|
||||
@ -14,7 +15,7 @@ mboot_mod_t modules_mboot[1] = {
|
||||
{0,0,0,1}
|
||||
};
|
||||
|
||||
struct multiboot multiboot_header = {
|
||||
static struct multiboot multiboot_header = {
|
||||
/* flags; */ MULTIBOOT_FLAG_CMDLINE | MULTIBOOT_FLAG_MODS | MULTIBOOT_FLAG_MEM | MULTIBOOT_FLAG_MMAP | MULTIBOOT_FLAG_LOADER,
|
||||
/* mem_lower; */ 0x100000,
|
||||
/* mem_upper; */ 0x640000,
|
||||
@ -43,22 +44,8 @@ struct multiboot multiboot_header = {
|
||||
|
||||
static uintptr_t ramdisk_off = 0;
|
||||
static uintptr_t ramdisk_len = 0;
|
||||
|
||||
uint32_t _eax = 1;
|
||||
uint32_t _ebx = 1;
|
||||
uint32_t _xmain = 1;
|
||||
|
||||
struct mmap_entry {
|
||||
uint64_t base;
|
||||
uint64_t len;
|
||||
uint32_t type;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
extern unsigned short mmap_ent;
|
||||
extern unsigned short lower_mem;
|
||||
|
||||
uintptr_t final_offset = 0;
|
||||
uintptr_t _xmain = 0;
|
||||
|
||||
static int load_kernel(void) {
|
||||
clear();
|
||||
@ -95,20 +82,453 @@ static int load_kernel(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void relocate_ramdisk(void) {
|
||||
static void relocate_ramdisk(mboot_mod_t * mboot_mods) {
|
||||
char * dest = (char*)final_offset;
|
||||
char * src = (char*)ramdisk_off;
|
||||
for (size_t s = 0; s < ramdisk_len; ++s) {
|
||||
dest[s] = src[s];
|
||||
}
|
||||
|
||||
modules_mboot[0].mod_start = final_offset;
|
||||
modules_mboot[0].mod_end = final_offset + ramdisk_len;
|
||||
mboot_mods->mod_start = final_offset;
|
||||
mboot_mods->mod_end = final_offset + ramdisk_len;
|
||||
|
||||
final_offset += ramdisk_len;
|
||||
final_offset = (final_offset & ~(0xFFF)) + ((final_offset & 0xFFF) ? 0x1000 : 0);
|
||||
}
|
||||
|
||||
#ifdef EFI_PLATFORM
|
||||
#include <efi.h>
|
||||
extern EFI_GRAPHICS_OUTPUT_PROTOCOL * GOP;
|
||||
|
||||
/* EFI boot uses simple filesystem driver */
|
||||
static EFI_GUID efi_simple_file_system_protocol_guid =
|
||||
{0x0964e5b22,0x6459,0x11d2,0x8e,0x39,0x00,0xa0,0xc9,0x69,0x72,0x3b};
|
||||
|
||||
static EFI_GUID efi_loaded_image_protocol_guid =
|
||||
{0x5B1B31A1,0x9562,0x11d2, {0x8E,0x3F,0x00,0xA0,0xC9,0x69,0x72,0x3B}};
|
||||
|
||||
extern EFI_SYSTEM_TABLE *ST;
|
||||
extern EFI_HANDLE ImageHandleIn;
|
||||
|
||||
extern char do_the_nasty[];
|
||||
static void finish_boot(void) {
|
||||
/* Set up multiboot header */
|
||||
struct multiboot * finalHeader = (void*)(uintptr_t)final_offset;
|
||||
memcpy((void*)final_offset, &multiboot_header, sizeof(struct multiboot));
|
||||
final_offset += sizeof(struct multiboot);
|
||||
|
||||
finalHeader->flags |= MULTIBOOT_FLAG_FB;
|
||||
finalHeader->framebuffer_addr = GOP->Mode->FrameBufferBase;
|
||||
finalHeader->framebuffer_pitch = GOP->Mode->Info->PixelsPerScanLine * 4;
|
||||
finalHeader->framebuffer_width = GOP->Mode->Info->HorizontalResolution;
|
||||
finalHeader->framebuffer_height = GOP->Mode->Info->VerticalResolution;
|
||||
finalHeader->framebuffer_bpp = 32;
|
||||
|
||||
/* Copy in command line */
|
||||
memcpy((void*)final_offset, cmdline, strlen(cmdline)+1);
|
||||
finalHeader->cmdline = (uintptr_t)final_offset;
|
||||
final_offset += strlen(cmdline) + 1;
|
||||
|
||||
/* Copy bootloader name */
|
||||
memcpy((void*)final_offset, VERSION_TEXT, strlen(VERSION_TEXT)+1);
|
||||
finalHeader->boot_loader_name = (uintptr_t)final_offset;
|
||||
final_offset += strlen(VERSION_TEXT) + 1;
|
||||
|
||||
/* Copy module pointers */
|
||||
memcpy((void*)final_offset, modules_mboot, sizeof(modules_mboot));
|
||||
finalHeader->mods_addr = (uintptr_t)final_offset;
|
||||
final_offset += sizeof(modules_mboot);
|
||||
|
||||
/* Realign for memory map */
|
||||
final_offset = (final_offset & ~(0xFFF)) + ((final_offset & 0xFFF) ? 0x1000 : 0);
|
||||
|
||||
/* Write memory map */
|
||||
mboot_memmap_t * mmap = (void*)final_offset;
|
||||
memset((void*)final_offset, 0x00, 1024);
|
||||
finalHeader->mmap_addr = (uint32_t)(uintptr_t)mmap;
|
||||
|
||||
{
|
||||
EFI_STATUS e;
|
||||
UINTN mapSize = 0, mapKey, descriptorSize;
|
||||
UINT32 descriptorVersion;
|
||||
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
|
||||
|
||||
EFI_MEMORY_DESCRIPTOR * efi_memory = (void*)(final_offset);
|
||||
final_offset += mapSize;
|
||||
while ((uintptr_t)final_offset & 0x3ff) final_offset++;
|
||||
|
||||
e = uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, efi_memory, &mapKey, &descriptorSize, NULL);
|
||||
|
||||
if (EFI_ERROR(e)) {
|
||||
print_("EFI error.\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
uint64_t upper_mem = 0;
|
||||
int descriptors = mapSize / descriptorSize;
|
||||
for (int i = 0; i < descriptors; ++i) {
|
||||
EFI_MEMORY_DESCRIPTOR * d = efi_memory;
|
||||
|
||||
mmap->size = sizeof(uint64_t) * 2 + sizeof(uint32_t);
|
||||
mmap->base_addr = d->PhysicalStart;
|
||||
mmap->length = d->NumberOfPages * 4096;
|
||||
switch (d->Type) {
|
||||
case EfiConventionalMemory:
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
case EfiBootServicesCode:
|
||||
case EfiBootServicesData:
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
mmap->type = 1;
|
||||
break;
|
||||
case EfiReservedMemoryType:
|
||||
case EfiUnusableMemory:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
case EfiPalCode:
|
||||
case EfiACPIMemoryNVS:
|
||||
case EfiACPIReclaimMemory:
|
||||
default:
|
||||
mmap->type = 2;
|
||||
break;
|
||||
}
|
||||
if (mmap->type == 1 && mmap->base_addr >= 0x100000) {
|
||||
upper_mem += mmap->length;
|
||||
}
|
||||
mmap = (mboot_memmap_t *) ((uintptr_t)mmap + mmap->size + sizeof(uint32_t));
|
||||
efi_memory = (EFI_MEMORY_DESCRIPTOR *)((char *)efi_memory + descriptorSize);
|
||||
}
|
||||
|
||||
finalHeader->mmap_length = (uintptr_t)mmap - finalHeader->mmap_addr;
|
||||
|
||||
finalHeader->mem_lower = 1024;
|
||||
finalHeader->mem_upper = upper_mem / 1024;
|
||||
}
|
||||
|
||||
relocate_ramdisk((void*)(uintptr_t)finalHeader->mods_addr);
|
||||
|
||||
{
|
||||
EFI_STATUS e;
|
||||
UINTN mapSize = 0, mapKey, descriptorSize;
|
||||
UINT32 descriptorVersion;
|
||||
uefi_call_wrapper(ST->BootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, NULL);
|
||||
e = uefi_call_wrapper(ST->BootServices->ExitBootServices, 2, ImageHandleIn, mapKey);
|
||||
|
||||
if (e != EFI_SUCCESS) {
|
||||
print_("Exit services failed. \n");
|
||||
print_hex_(e);
|
||||
while (1) {};
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t foobar = ((uint32_t)(uintptr_t)&do_the_nasty) | (0x10L << 32L);
|
||||
|
||||
uint32_t * foo = (uint32_t *)0x7c00;
|
||||
|
||||
foo[0] = MULTIBOOT_EAX_MAGIC;
|
||||
foo[1] = (uintptr_t)finalHeader;
|
||||
foo[2] = _xmain;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"push %0\n"
|
||||
"lretl\n"
|
||||
: : "g"(foobar));
|
||||
|
||||
__asm__ (
|
||||
"do_the_nasty:\n"
|
||||
"cli\n"
|
||||
".code32\n"
|
||||
"mov %cr0, %eax\n"
|
||||
"and $0x7FFeFFFF, %eax\n"
|
||||
"mov %eax, %cr0\n"
|
||||
"mov $0xc0000080, %ecx\n"
|
||||
"rdmsr\n"
|
||||
"and $0xfffffeff, %eax\n"
|
||||
"wrmsr\n"
|
||||
"mov $0x640, %eax\n"
|
||||
"mov %eax, %cr4\n"
|
||||
"mov 0x7c00, %eax\n"
|
||||
"mov 0x7c04, %ebx\n"
|
||||
"mov 0x7c08, %ecx\n"
|
||||
"jmp *%ecx\n"
|
||||
"target: jmp target\n"
|
||||
".code64\n"
|
||||
);
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void mode_selector(int sel, int ndx, char *str) {
|
||||
set_attr(sel == ndx ? 0x70 : 0x07);
|
||||
print_(str);
|
||||
if (x < 40) {
|
||||
while (x < 39) {
|
||||
print_(" ");
|
||||
}
|
||||
x = 40;
|
||||
} else {
|
||||
print_("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static char * print_int_into(char * str, unsigned int value) {
|
||||
unsigned int n_width = 1;
|
||||
unsigned int i = 9;
|
||||
while (value > i && i < UINT32_MAX) {
|
||||
n_width += 1;
|
||||
i *= 10;
|
||||
i += 9;
|
||||
}
|
||||
|
||||
char buf[n_width+1];
|
||||
for (int i = 0; i < n_width + 1; i++) {
|
||||
buf[i] = 0;
|
||||
}
|
||||
i = n_width;
|
||||
while (i > 0) {
|
||||
unsigned int n = value / 10;
|
||||
int r = value % 10;
|
||||
buf[i - 1] = r + '0';
|
||||
i--;
|
||||
value = n;
|
||||
}
|
||||
for (char * c = buf; *c; c++) {
|
||||
*str++ = *c;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
int video_menu(void) {
|
||||
clear_();
|
||||
|
||||
int sel = 0;
|
||||
int sel_max = GOP->Mode->MaxMode;
|
||||
int select_this_mode = 0;
|
||||
|
||||
do {
|
||||
move_cursor(0,0);
|
||||
set_attr(0x1f);
|
||||
print_banner("Select Video Mode");
|
||||
set_attr(0x07);
|
||||
print_("\n");
|
||||
|
||||
for (int i = 0; i < GOP->Mode->MaxMode; ++i) {
|
||||
EFI_STATUS status;
|
||||
UINTN size;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION * info;
|
||||
|
||||
status = uefi_call_wrapper(GOP->QueryMode,
|
||||
4, GOP, i, &size, &info);
|
||||
|
||||
if (EFI_ERROR(status) || info->PixelFormat != 1) {
|
||||
mode_selector(sel, i, "[invalid]");
|
||||
} else {
|
||||
|
||||
if (select_this_mode && sel == i) {
|
||||
uefi_call_wrapper(GOP->SetMode, 2, GOP, i);
|
||||
extern int init_graphics();
|
||||
init_graphics();
|
||||
return 0;
|
||||
}
|
||||
|
||||
char tmp[100];
|
||||
char * t = tmp;
|
||||
t = print_int_into(t, info->HorizontalResolution); *t = 'x'; t++;
|
||||
t = print_int_into(t, info->VerticalResolution); *t = '\0';
|
||||
mode_selector(sel, i, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
int s = read_scancode(0);
|
||||
if (s == 0x50) { /* DOWN */
|
||||
if (sel >= 0 && sel < sel_max - 1) {
|
||||
sel = (sel + 2) % sel_max;
|
||||
} else {
|
||||
sel = (sel + 1) % sel_max;
|
||||
}
|
||||
} else if (s == 0x48) { /* UP */
|
||||
if (sel >= 1) {
|
||||
sel = (sel_max + sel - 2) % sel_max;
|
||||
} else {
|
||||
sel = (sel_max + sel - 1) % sel_max;
|
||||
}
|
||||
} else if (s == 0x4B) { /* LEFT */
|
||||
if (sel >= 0) {
|
||||
if ((sel + 1) % 2) {
|
||||
sel = (sel + 1) % sel_max;
|
||||
} else {
|
||||
sel -= 1;
|
||||
}
|
||||
}
|
||||
} else if (s == 0x4D) { /* RIGHT */
|
||||
if (sel >= 0) {
|
||||
if ((sel + 1) % 2) {
|
||||
sel = (sel + 1) % sel_max;
|
||||
} else {
|
||||
sel -= 1;
|
||||
}
|
||||
}
|
||||
} else if (s == 0x1c) {
|
||||
select_this_mode = 1;
|
||||
continue;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
}
|
||||
|
||||
void boot(void) {
|
||||
UINTN count;
|
||||
EFI_HANDLE * handles;
|
||||
EFI_LOADED_IMAGE * loaded_image;
|
||||
EFI_FILE_IO_INTERFACE *efi_simple_filesystem;
|
||||
EFI_FILE *root;
|
||||
EFI_STATUS status;
|
||||
|
||||
uefi_call_wrapper(ST->BootServices->SetWatchdogTimer, 4, 0, 0, 0, NULL);
|
||||
|
||||
clear_();
|
||||
|
||||
for (unsigned int i = 0; i < ST->NumberOfTableEntries; ++i) {
|
||||
if (ST->ConfigurationTable[i].VendorGuid.Data1 == 0xeb9d2d30 &&
|
||||
ST->ConfigurationTable[i].VendorGuid.Data2 == 0x2d88 &&
|
||||
ST->ConfigurationTable[i].VendorGuid.Data3 == 0x11d3) {
|
||||
multiboot_header.config_table = (uintptr_t)ST->ConfigurationTable[i].VendorTable & 0xFFFFffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
||||
3, ImageHandleIn, &efi_loaded_image_protocol_guid,
|
||||
(void **)&loaded_image);
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Could not obtain loaded_image_protocol\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
print("Found loaded image...\n");
|
||||
|
||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
||||
3, loaded_image->DeviceHandle, &efi_simple_file_system_protocol_guid,
|
||||
(void **)&efi_simple_filesystem);
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Could not obtain simple_file_system_protocol.\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
status = uefi_call_wrapper(efi_simple_filesystem->OpenVolume,
|
||||
2, efi_simple_filesystem, &root);
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Could not open volume.\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
EFI_FILE * file;
|
||||
|
||||
CHAR16 kernel_name[16] = {0};
|
||||
{
|
||||
char * c = kernel_path;
|
||||
char * ascii = c;
|
||||
int i = 0;
|
||||
while (*ascii) {
|
||||
kernel_name[i] = *ascii;
|
||||
i++;
|
||||
ascii++;
|
||||
}
|
||||
if (kernel_name[i-1] == L'.') {
|
||||
kernel_name[i-1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load kernel */
|
||||
status = uefi_call_wrapper(root->Open,
|
||||
5, root, &file, kernel_name, EFI_FILE_MODE_READ, 0);
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Error opening kernel.\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
#define KERNEL_LOAD_START 0x4000000ULL
|
||||
kernel_load_start = (char*)KERNEL_LOAD_START;
|
||||
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS addr = KERNEL_LOAD_START;
|
||||
EFI_ALLOCATE_TYPE type = AllocateAddress;
|
||||
EFI_MEMORY_TYPE memtype = EfiLoaderData;
|
||||
UINTN pages = 8192;
|
||||
EFI_STATUS status = 0;
|
||||
status = uefi_call_wrapper(ST->BootServices->AllocatePages, 4, type, memtype, pages, &addr);
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Could not allocate space to load boot payloads: ");
|
||||
print_hex_(status);
|
||||
print_(" ");
|
||||
print_hex_(addr);
|
||||
while (1) {};
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int offset = 0;
|
||||
UINTN bytes = 134217728;
|
||||
status = uefi_call_wrapper(file->Read,
|
||||
3, file, &bytes, (void *)KERNEL_LOAD_START);
|
||||
|
||||
if (EFI_ERROR(status)) {
|
||||
print_("Error loading kernel.\n");
|
||||
while (1) {};
|
||||
}
|
||||
|
||||
offset += bytes;
|
||||
while (offset % 4096) offset++;
|
||||
|
||||
{
|
||||
char * c = ramdisk_path;
|
||||
CHAR16 name[16] = {0};
|
||||
char * ascii = c;
|
||||
int i = 0;
|
||||
while (*ascii) {
|
||||
name[i] = *ascii;
|
||||
i++;
|
||||
ascii++;
|
||||
}
|
||||
if (name[i-1] == L'.') {
|
||||
name[i-1] == 0;
|
||||
}
|
||||
bytes = 134217728;
|
||||
status = uefi_call_wrapper(root->Open,
|
||||
5, root, &file, name, EFI_FILE_MODE_READ, 0);
|
||||
if (!EFI_ERROR(status)) {
|
||||
status = uefi_call_wrapper(file->Read,
|
||||
3, file, &bytes, (void*)(uintptr_t)(KERNEL_LOAD_START + offset));
|
||||
if (!EFI_ERROR(status)) {
|
||||
ramdisk_off = KERNEL_LOAD_START + offset;
|
||||
ramdisk_len = bytes;
|
||||
} else {
|
||||
print_("Failed to read ramdisk\n");
|
||||
}
|
||||
} else {
|
||||
print_("Error opening "); print_(c); print_("\n");
|
||||
}
|
||||
}
|
||||
|
||||
load_kernel();
|
||||
finish_boot();
|
||||
}
|
||||
|
||||
#else
|
||||
struct mmap_entry {
|
||||
uint64_t base;
|
||||
uint64_t len;
|
||||
uint32_t type;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
extern unsigned short mmap_ent;
|
||||
extern unsigned short lower_mem;
|
||||
|
||||
static void finish_boot(void) {
|
||||
print("Setting up memory map...\n");
|
||||
print_hex(mmap_ent);
|
||||
@ -148,14 +568,11 @@ static void finish_boot(void) {
|
||||
|
||||
multiboot_header.mem_upper = upper_mem / 1024;
|
||||
|
||||
_ebx = (unsigned int)&multiboot_header;
|
||||
_eax = MULTIBOOT_EAX_MAGIC;
|
||||
|
||||
print("Jumping to kernel...\n");
|
||||
|
||||
uint32_t foo[3];
|
||||
foo[0] = _eax;
|
||||
foo[1] = _ebx;
|
||||
foo[0] = MULTIBOOT_EAX_MAGIC;
|
||||
foo[1] = (unsigned int)&multiboot_header;;
|
||||
foo[2] = _xmain;
|
||||
__asm__ __volatile__ (
|
||||
"mov %%cr0,%%eax\n"
|
||||
@ -214,7 +631,7 @@ done:
|
||||
}
|
||||
|
||||
print("Relocating ramdisk from 0x"); print_hex((uint32_t)ramdisk_off); print(":0x"); print_hex(ramdisk_len); print(" to 0x"); print_hex(final_offset); print("... ");
|
||||
relocate_ramdisk();
|
||||
relocate_ramdisk(modules_mboot);
|
||||
finish_boot();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -27,6 +27,12 @@ struct bootmode {
|
||||
#define BASE_SEL ((sizeof(boot_mode_names)/sizeof(*boot_mode_names))-1)
|
||||
extern int base_sel;
|
||||
|
||||
#define BOOT_SET() do { \
|
||||
base_sel = BASE_SEL; \
|
||||
_boot_offset = 0; \
|
||||
memset(boot_options, 0, sizeof(boot_options)); \
|
||||
} while (0)
|
||||
|
||||
extern char * VERSION_TEXT;
|
||||
extern char * HELP_TEXT;
|
||||
extern char * HELP_TEXT_OPT;
|
||||
|
107
boot/platform.c
Normal file
107
boot/platform.c
Normal file
@ -0,0 +1,107 @@
|
||||
extern int kmain();
|
||||
|
||||
#ifdef EFI_PLATFORM
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
EFI_HANDLE ImageHandleIn;
|
||||
|
||||
extern int init_graphics();
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
|
||||
{
|
||||
InitializeLib(ImageHandle, SystemTable);
|
||||
ST = SystemTable;
|
||||
ImageHandleIn = ImageHandle;
|
||||
|
||||
init_graphics();
|
||||
|
||||
return kmain();
|
||||
}
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "iso9660.h"
|
||||
#include "util.h"
|
||||
#include "text.h"
|
||||
extern char _bss_start[];
|
||||
extern char _bss_end[];
|
||||
|
||||
void * memcpy(void * restrict dest, const void * restrict src, long n) {
|
||||
asm volatile("cld; rep movsb"
|
||||
: "=c"((int){0})
|
||||
: "D"(dest), "S"(src), "c"(n)
|
||||
: "flags", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
void * memset(void * dest, int c, long n) {
|
||||
asm volatile("cld; rep stosb"
|
||||
: "=c"((int){0})
|
||||
: "D"(dest), "a"(c), "c"(n)
|
||||
: "flags", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
int bios_main(void) {
|
||||
/* Zero BSS */
|
||||
memset(&_bss_start,0,(uintptr_t)&_bss_end-(uintptr_t)&_bss_start);
|
||||
|
||||
/* Hide the cursor */
|
||||
outportb(0x3D4, 14);
|
||||
outportb(0x3D5, 0xFF);
|
||||
outportb(0x3D4, 15);
|
||||
outportb(0x3D5, 0xFF);
|
||||
|
||||
/* iirc this disables blink? */
|
||||
inportb(0x3DA);
|
||||
outportb(0x3C0, 0x30);
|
||||
char b = inportb(0x3C1);
|
||||
b &= ~8;
|
||||
outportb(0x3c0, b);
|
||||
|
||||
return kmain();
|
||||
}
|
||||
|
||||
iso_9660_volume_descriptor_t * root = NULL;
|
||||
iso_9660_directory_entry_t * dir_entry = NULL;
|
||||
static char * dir_entries = NULL;
|
||||
|
||||
int navigate(char * name) {
|
||||
dir_entry = (iso_9660_directory_entry_t*)&root->root;
|
||||
dir_entries = (char*)(DATA_LOAD_BASE + dir_entry->extent_start_LSB * ISO_SECTOR_SIZE);
|
||||
long offset = 0;
|
||||
while (1) {
|
||||
iso_9660_directory_entry_t * dir = (iso_9660_directory_entry_t *)(dir_entries + offset);
|
||||
if (dir->length == 0) {
|
||||
if (offset < dir_entry->extent_length_LSB) {
|
||||
offset += 1;
|
||||
goto try_again;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!(dir->flags & FLAG_HIDDEN)) {
|
||||
char file_name[dir->name_len + 1];
|
||||
memcpy(file_name, dir->name, dir->name_len);
|
||||
file_name[dir->name_len] = 0;
|
||||
char * s = strchr(file_name,';');
|
||||
if (s) {
|
||||
*s = '\0';
|
||||
}
|
||||
if (!strcmp(file_name, name)) {
|
||||
dir_entry = dir;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
offset += dir->length;
|
||||
try_again:
|
||||
if ((long)(offset) > dir_entry->extent_length_LSB) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
128
boot/text.c
128
boot/text.c
@ -1,7 +1,113 @@
|
||||
#include "text.h"
|
||||
|
||||
#include "util.h"
|
||||
int txt_debug = 0;
|
||||
|
||||
#ifdef EFI_PLATFORM
|
||||
#include <efi.h>
|
||||
extern EFI_SYSTEM_TABLE *ST;
|
||||
|
||||
#include "../apps/terminal-font.h"
|
||||
|
||||
#define char_height LARGE_FONT_CELL_HEIGHT
|
||||
#define char_width LARGE_FONT_CELL_WIDTH
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL * GOP;
|
||||
|
||||
static int offset_x = 0;
|
||||
static int offset_y = 0;
|
||||
|
||||
static EFI_GUID efi_graphics_output_protocol_guid =
|
||||
{0x9042a9de,0x23dc,0x4a38, {0x96,0xfb,0x7a,0xde,0xd0,0x80,0x51,0x6a}};
|
||||
|
||||
int init_graphics() {
|
||||
UINTN count;
|
||||
EFI_HANDLE * handles;
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL * gfx;
|
||||
EFI_STATUS status;
|
||||
|
||||
status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer,
|
||||
5, ByProtocol, &efi_graphics_output_protocol_guid, NULL, &count, &handles);
|
||||
if (EFI_ERROR(status)) goto no_graphics;
|
||||
status = uefi_call_wrapper(ST->BootServices->HandleProtocol,
|
||||
3, handles[0], &efi_graphics_output_protocol_guid, (void **)&gfx);
|
||||
if (EFI_ERROR(status)) goto no_graphics;
|
||||
|
||||
GOP = gfx;
|
||||
|
||||
int total_width = GOP->Mode->Info->HorizontalResolution;
|
||||
int total_height = GOP->Mode->Info->VerticalResolution;
|
||||
|
||||
offset_x = (total_width - 80 * char_width) / 2;
|
||||
offset_y = (total_height - 24 * char_height) / 2;
|
||||
|
||||
return 0;
|
||||
|
||||
no_graphics:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t term_colors[] = {
|
||||
0xFF000000,
|
||||
0xFFCC0000,
|
||||
0xFF4E9A06,
|
||||
0xFFC4A000,
|
||||
0xFF3465A4,
|
||||
0xFF75507B,
|
||||
0xFF06989A,
|
||||
0xFFD3D7CF,
|
||||
|
||||
0xFF555753,
|
||||
0xFFEF2929,
|
||||
0xFF8AE234,
|
||||
0xFFFCE94F,
|
||||
0xFF729FCF,
|
||||
0xFFAD7FA8,
|
||||
0xFF34E2E2,
|
||||
0xFFEEEEEC,
|
||||
};
|
||||
|
||||
char vga_to_ansi[] = {
|
||||
0, 4, 2, 6, 1, 5, 3, 7,
|
||||
8,12,10,14, 9,13,11,15
|
||||
};
|
||||
|
||||
static void set_point(int x, int y, uint32_t color) {
|
||||
|
||||
((uint32_t *)GOP->Mode->FrameBufferBase)[(x + offset_x) + (y + offset_y) * GOP->Mode->Info->PixelsPerScanLine] = color;
|
||||
}
|
||||
|
||||
static void write_char(int x, int y, int val, int attr) {
|
||||
if (val > 128) {
|
||||
val = 4;
|
||||
}
|
||||
|
||||
uint32_t fg_color = term_colors[vga_to_ansi[attr & 0xF]];
|
||||
uint32_t bg_color = term_colors[vga_to_ansi[(attr >> 4) & 0xF]];
|
||||
|
||||
uint16_t * c = large_font[val];
|
||||
for (uint8_t i = 0; i < char_height; ++i) {
|
||||
for (uint8_t j = 0; j < char_width; ++j) {
|
||||
if (c[i] & (1 << (LARGE_FONT_MASK-j))) {
|
||||
set_point(x+j,y+i,fg_color);
|
||||
} else {
|
||||
set_point(x+j,y+i,bg_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void placech(unsigned char c, int x, int y, int attr) {
|
||||
write_char(x * char_width, y * char_height, c, attr);
|
||||
}
|
||||
|
||||
void clear_() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
memset((void*)GOP->Mode->FrameBufferBase,0,GOP->Mode->FrameBufferSize);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static unsigned short * textmemptr = (unsigned short *)0xB8000;
|
||||
|
||||
static void placech(unsigned char c, int x, int y, int attr) {
|
||||
@ -11,6 +117,17 @@ static void placech(unsigned char c, int x, int y, int attr) {
|
||||
*where = c | att;
|
||||
}
|
||||
|
||||
void clear_() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (int y = 0; y < 24; ++y) {
|
||||
for (int x = 0; x < 80; ++x) {
|
||||
placech(' ', x, y, 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int attr = 0x07;
|
||||
@ -84,12 +201,3 @@ void print_hex_(unsigned int value) {
|
||||
print_(out);
|
||||
}
|
||||
|
||||
void clear_() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
for (int y = 0; y < 24; ++y) {
|
||||
for (int x = 0; x < 80; ++x) {
|
||||
placech(' ', x, y, 0x00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
boot/util.c
16
boot/util.c
@ -1,21 +1,5 @@
|
||||
#include "util.h"
|
||||
|
||||
void * memcpy(void * restrict dest, const void * restrict src, long n) {
|
||||
asm volatile("cld; rep movsb"
|
||||
: "=c"((int){0})
|
||||
: "D"(dest), "S"(src), "c"(n)
|
||||
: "flags", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
void * memset(void * dest, int c, long n) {
|
||||
asm volatile("cld; rep stosb"
|
||||
: "=c"((int){0})
|
||||
: "D"(dest), "a"(c), "c"(n)
|
||||
: "flags", "memory");
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char * l, const char * r) {
|
||||
for (; *l == *r && *l; l++, r++);
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
|
Loading…
Reference in New Issue
Block a user