diff --git a/Makefile b/Makefile index 26061861..4969da33 100644 --- a/Makefile +++ b/Makefile @@ -40,19 +40,19 @@ limine-install: limine-install.c test.hdd: rm -f test.hdd dd if=/dev/zero bs=1M count=0 seek=64 of=test.hdd - parted -s test.hdd mklabel msdos + parted -s test.hdd mklabel gpt parted -s test.hdd mkpart primary 2048s 100% echfs-test: all limine-install test.hdd $(MAKE) -C test - echfs-utils -m -p0 test.hdd quick-format 512 > part_guid + echfs-utils -g -p0 test.hdd quick-format 512 > part_guid sed "s/@GUID@/`cat part_guid`/g" < test/limine.cfg > limine.cfg.tmp - echfs-utils -m -p0 test.hdd import limine.cfg.tmp limine.cfg + echfs-utils -g -p0 test.hdd import limine.cfg.tmp limine.cfg rm -f limine.cfg.tmp part_guid - echfs-utils -m -p0 test.hdd import stage2.map boot/stage2.map - echfs-utils -m -p0 test.hdd import test/test.elf boot/test.elf - echfs-utils -m -p0 test.hdd import test/bg.bmp boot/bg.bmp - echfs-utils -m -p0 test.hdd import test/font.bin boot/font.bin + echfs-utils -g -p0 test.hdd import stage2.map boot/stage2.map + echfs-utils -g -p0 test.hdd import test/test.elf boot/test.elf + echfs-utils -g -p0 test.hdd import test/bg.bmp boot/bg.bmp + echfs-utils -g -p0 test.hdd import test/font.bin boot/font.bin ./limine-install limine.bin test.hdd qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio diff --git a/bootsect/bootsect.asm b/bootsect/bootsect.asm index 466e4f2f..53d9bc85 100644 --- a/bootsect/bootsect.asm +++ b/bootsect/bootsect.asm @@ -54,37 +54,31 @@ start: ; make sure that is the case now. mov esp, 0x7c00 - push 0x6fe0 + push 0x7000 pop es - mov eax, dword [stage2_sector] + mov di, stage2_locs + mov eax, dword [di] + mov ebp, dword [di+4] xor bx, bx - mov ecx, 32768 + xor ecx, ecx + mov cx, word [di-4] + call read_sectors + jc err + mov eax, dword [di+8] + mov ebp, dword [di+12] + add bx, cx + mov cx, word [di-2] call read_sectors jc err - call load_gdt + lgdt [gdt] cli - mov eax, cr0 bts ax, 0 mov cr0, eax - jmp 0x18:.mode32 - bits 32 - .mode32: - mov ax, 0x20 - mov ds, ax - mov es, ax - mov fs, ax - mov gs, ax - mov ss, ax - - and edx, 0xff - - jmp vector - -bits 16 + jmp 0x08:vector err: hlt @@ -100,6 +94,15 @@ times 6 db 0 bits 32 vector: + mov eax, 0x10 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + and edx, 0xff + push 0 push edx @@ -109,10 +112,12 @@ vector: call 0x70000 -bits 16 - -times 0x1b0-($-$$) db 0 -stage2_sector: dd 0 +times 0x1a4-($-$$) db 0 +stage2_size_a: dw 0 +stage2_size_b: dw 0 +stage2_locs: +stage2_loc_a: dq 0 +stage2_loc_b: dq 0 times 0x1b8-($-$$) db 0 times 510-($-$$) db 0 @@ -127,5 +132,3 @@ align 16 stage2: incbin '../stage2/stage2.bin.gz' .size: equ $ - stage2 - -times 32768-($-$$) db 0 diff --git a/bootsect/disk.inc b/bootsect/disk.inc index 0886dbef..716cb19b 100644 --- a/bootsect/disk.inc +++ b/bootsect/disk.inc @@ -1,9 +1,10 @@ -; *********************************************** -; Reads a disk sector with an LBA address -; *********************************************** +; ***************************** +; Reads bytes from disk +; ***************************** ; IN: -; EAX = LBA sector to load +; EAX = Start address to load low 32 +; EBP = Start address to load high 32 ; DL = Drive number ; ES = Buffer segment ; BX = Buffer offset @@ -15,32 +16,47 @@ read_sectors: pusha - mov esi, .da_struct + mov si, .da_struct mov word [si], 16 mov word [si+2], 1 mov word [si+4], bx mov word [si+6], es - mov dword [si+8], eax - mov dword [si+12], 0 - ; Get bytes per sector push dx push si + + push eax + push ebp + + ; Get bytes per sector mov ah, 0x48 mov si, .drive_params mov word [si], 30 ; buf_size int 0x13 jc .done mov bp, word [si+24] ; bytes_per_sect + + ; ECX byte count to CX sector count mov ax, cx shr ecx, 16 mov dx, cx xor cx, cx div bp test dx, dx - adc cx, ax + setnz cl + add cx, ax + + pop edx + pop eax + pop si + + ; EBP:EAX address to EAX LBA sector + div ebp + mov dword [si+8], eax + mov dword [si+12], edx + pop dx .loop: @@ -52,6 +68,7 @@ read_sectors: add word [si+4], bp inc dword [si+8] + adc dword [si+12], 0 loop .loop diff --git a/bootsect/gdt.inc b/bootsect/gdt.inc index e8735424..6c4c3638 100644 --- a/bootsect/gdt.inc +++ b/bootsect/gdt.inc @@ -1,55 +1,8 @@ -%define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b)) -%define ALIGN_UP(x, a) (DIV_ROUNDUP((x), (a)) * (a)) - -; The GDT is copied to - gdt.size, which will also serve -; as the upper limit for balloc() -load_gdt: - pusha - push es - mov ax, word [0x40e] ; 0x40e contains the value of a segment pointing to the EBDA - sub ax, ALIGN_UP(gdt.size, 16) / 16 - mov es, ax - mov word [gdt.ptr], ax - shl dword [gdt.ptr], 4 - xor di, di - mov si, gdt.start - mov cx, gdt.size - rep movsb - lgdt [gdt] - pop es - popa - ret - gdt: - dw .size - 1 ; GDT size - .ptr: - dd 0 ; GDT start address (calculated at runtime) + dw .size - 1 + 8 ; GDT size + dd .start - 8 ; GDT start address .start: - ; Null descriptor (required) - dw 0x0000 ; Limit - dw 0x0000 ; Base (low 16 bits) - db 0x00 ; Base (mid 8 bits) - db 00000000b ; Access - db 00000000b ; Granularity - db 0x00 ; Base (high 8 bits) - - ; 16-bit code - dw 0xffff ; Limit - dw 0x0000 ; Base (low 16 bits) - db 0x00 ; Base (mid 8 bits) - db 10011010b ; Access - db 00000000b ; Granularity - db 0x00 ; Base (high 8 bits) - - ; 16-bit data - dw 0xffff ; Limit - dw 0x0000 ; Base (low 16 bits) - db 0x00 ; Base (mid 8 bits) - db 10010010b ; Access - db 00000000b ; Granularity - db 0x00 ; Base (high 8 bits) - ; 32-bit code dw 0xffff ; Limit dw 0x0000 ; Base (low 16 bits) @@ -66,22 +19,6 @@ gdt: db 11001111b ; Granularity db 0x00 ; Base (high 8 bits) - ; 64-bit code - dw 0x0000 ; Limit - dw 0x0000 ; Base (low 16 bits) - db 0x00 ; Base (mid 8 bits) - db 10011010b ; Access - db 00100000b ; Granularity - db 0x00 ; Base (high 8 bits) - - ; 64-bit data - dw 0x0000 ; Limit - dw 0x0000 ; Base (low 16 bits) - db 0x00 ; Base (mid 8 bits) - db 10010010b ; Access - db 00000000b ; Granularity - db 0x00 ; Base (high 8 bits) - .end: .size: equ .end - .start diff --git a/limine-install.c b/limine-install.c index 9a73c50b..e45c1c0a 100644 --- a/limine-install.c +++ b/limine-install.c @@ -2,16 +2,100 @@ #include #include #include +#include +#include #include +struct gpt_table_header { + // the head + char signature[8]; + uint32_t revision; + uint32_t header_size; + uint32_t crc32; + uint32_t _reserved0; + + // the partitioning info + uint64_t my_lba; + uint64_t alternate_lba; + uint64_t first_usable_lba; + uint64_t last_usable_lba; + + // the guid + uint64_t disk_guid[2]; + + // entries related + uint64_t partition_entry_lba; + uint32_t number_of_partition_entries; + uint32_t size_of_partition_entry; + uint32_t partition_entry_array_crc32; +} __attribute__((packed)); + +// This table from https://web.mit.edu/freebsd/head/sys/libkern/crc32.c +const uint32_t crc32_table[] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static uint32_t crc32(void *_stream, size_t len) { + uint8_t *stream = _stream; + uint32_t ret = 0xffffffff; + + for (size_t i = 0; i < len; i++) { + ret = (ret >> 8) ^ crc32_table[(ret ^ stream[i]) & 0xff]; + } + + ret ^= 0xffffffff; + return ret; +} + int main(int argc, char *argv[]) { FILE *bootloader_file, *device; uint8_t *bootloader_img; uint8_t orig_mbr[70], timestamp[6]; - uint32_t stage2_sect, sect_size; if (argc < 3) { - printf("Usage: %s [ ]\n", argv[0]); + printf("Usage: %s \n", argv[0]); return 1; } @@ -21,8 +105,10 @@ int main(int argc, char *argv[]) { return 1; } - // The bootloader image is 64 sectors (32k) - bootloader_img = malloc(64 * 512); + fseek(bootloader_file, 0, SEEK_END); + size_t bootloader_file_size = ftell(bootloader_file); + + bootloader_img = malloc(bootloader_file_size); if (bootloader_img == NULL) { perror("Error: "); fclose(bootloader_file); @@ -31,7 +117,7 @@ int main(int argc, char *argv[]) { // Load in bootloader image fseek(bootloader_file, 0, SEEK_SET); - fread(bootloader_img, 64, 512, bootloader_file); + fread(bootloader_img, 1, bootloader_file_size, bootloader_file); fclose(bootloader_file); device = fopen(argv[2], "r+b"); @@ -41,12 +127,96 @@ int main(int argc, char *argv[]) { return 1; } - stage2_sect = 0; - sect_size = 512; - if (argc >= 4) - sscanf(argv[3], "%" SCNu32, &stage2_sect); - if (argc >= 5) - sscanf(argv[4], "%" SCNu32, §_size); + // Probe for GPT and logical block size + int gpt = 0; + struct gpt_table_header gpt_header; + int lb_guesses[] = { 512, 4096 }; + int lb_size; + for (size_t i = 0; i < sizeof(lb_guesses) / sizeof(int); i++) { + fseek(device, lb_guesses[i], SEEK_SET); + fread(&gpt_header, sizeof(struct gpt_table_header), 1, device); + if (!strncmp(gpt_header.signature, "EFI PART", 8)) { + gpt = 1; + lb_size = lb_guesses[i]; + fprintf(stderr, "Installing to GPT. Logical block size of %d bytes.\n", + lb_guesses[i]); + break; + } + } + + struct gpt_table_header secondary_gpt_header; + if (gpt) { + fprintf(stderr, "Secondary header at LBA 0x%" PRIx64 ".\n", + gpt_header.alternate_lba); + fseek(device, lb_size * gpt_header.alternate_lba, SEEK_SET); + fread(&secondary_gpt_header, sizeof(struct gpt_table_header), 1, device); + if (!strncmp(secondary_gpt_header.signature, "EFI PART", 8)) { + fprintf(stderr, "Secondary header valid.\n"); + } else { + fprintf(stderr, "Secondary header not valid, aborting.\n"); + abort(); + } + } + + size_t stage2_size = bootloader_file_size - 512; + uint16_t stage2_size_a = stage2_size / 2 + stage2_size % 2; + uint16_t stage2_size_b = stage2_size / 2; + + // Default split of stage2 for MBR (consecutive in post MBR gap) + uint64_t stage2_loc_a = 512; + uint64_t stage2_loc_b = stage2_loc_a + stage2_size_a; + if (stage2_loc_b & 512) + stage2_loc_b = (stage2_loc_b + 512) & ~(512 - 1); + + if (gpt) { + stage2_loc_a = (gpt_header.partition_entry_lba + 32) * lb_size; + stage2_loc_a -= stage2_size_a; + stage2_loc_a &= ~(lb_size - 1); + stage2_loc_b = (secondary_gpt_header.partition_entry_lba + 32) * lb_size; + stage2_loc_b -= stage2_size_b; + stage2_loc_b &= ~(lb_size - 1); + + size_t partition_entries_per_lb = + lb_size / gpt_header.size_of_partition_entry; + size_t new_partition_array_lba_size = + stage2_loc_a / lb_size - gpt_header.partition_entry_lba; + size_t new_partition_entry_count = + new_partition_array_lba_size * partition_entries_per_lb; + + uint8_t *partition_array = + malloc(new_partition_entry_count * gpt_header.size_of_partition_entry); + assert(partition_array); + + fseek(device, gpt_header.partition_entry_lba * lb_size, SEEK_SET); + fread(partition_array, + new_partition_entry_count * gpt_header.size_of_partition_entry, + 1, device); + + uint32_t crc32_partition_array = + crc32(partition_array, + new_partition_entry_count * gpt_header.size_of_partition_entry); + + free(partition_array); + + gpt_header.partition_entry_array_crc32 = crc32_partition_array; + gpt_header.number_of_partition_entries = new_partition_entry_count; + gpt_header.crc32 = 0; + gpt_header.crc32 = crc32(&gpt_header, sizeof(struct gpt_table_header)); + fseek(device, lb_size, SEEK_SET); + fwrite(&gpt_header, sizeof(struct gpt_table_header), 1, device); + + secondary_gpt_header.partition_entry_array_crc32 = crc32_partition_array; + secondary_gpt_header.number_of_partition_entries = + new_partition_entry_count; + secondary_gpt_header.crc32 = 0; + secondary_gpt_header.crc32 = + crc32(&secondary_gpt_header, sizeof(struct gpt_table_header)); + fseek(device, lb_size * gpt_header.alternate_lba, SEEK_SET); + fwrite(&secondary_gpt_header, sizeof(struct gpt_table_header), 1, device); + } + + fprintf(stderr, "Stage 2 to be located at 0x%" PRIx64 " and 0x%" PRIx64 ".\n", + stage2_loc_a, stage2_loc_b); // Save original timestamp fseek(device, 218, SEEK_SET); @@ -61,12 +231,17 @@ int main(int argc, char *argv[]) { fwrite(&bootloader_img[0], 1, 512, device); // Write the rest of stage 2 to the device - fseek(device, stage2_sect * sect_size, SEEK_SET); - fwrite(&bootloader_img[0], 64, 512, device); + fseek(device, stage2_loc_a, SEEK_SET); + fwrite(&bootloader_img[512], 1, stage2_size_a, device); + fseek(device, stage2_loc_b, SEEK_SET); + fwrite(&bootloader_img[512 + stage2_size_a], 1, stage2_size_b, device); - // Hardcode in the bootsector the location of stage 2 - fseek(device, 0x1b0, SEEK_SET); - fwrite(&stage2_sect, 1, sizeof(uint32_t), device); + // Hardcode in the bootsector the location of stage 2 halves + fseek(device, 0x1a4, SEEK_SET); + fwrite(&stage2_size_a, 1, sizeof(uint16_t), device); + fwrite(&stage2_size_b, 1, sizeof(uint16_t), device); + fwrite(&stage2_loc_a, 1, sizeof(uint64_t), device); + fwrite(&stage2_loc_b, 1, sizeof(uint64_t), device); // Write back timestamp fseek(device, 218, SEEK_SET); diff --git a/limine-pxe.bin b/limine-pxe.bin index 6f7b527b..7104431f 100644 Binary files a/limine-pxe.bin and b/limine-pxe.bin differ diff --git a/limine.bin b/limine.bin index c9ea74c2..60383bde 100644 Binary files a/limine.bin and b/limine.bin differ diff --git a/pxeboot/bootsect.asm b/pxeboot/bootsect.asm index a082d441..ad033ef5 100644 --- a/pxeboot/bootsect.asm +++ b/pxeboot/bootsect.asm @@ -10,7 +10,7 @@ start: mov ss, ax mov sp, 0x7c00 sti - call load_gdt + lgdt [gdt] cli @@ -18,10 +18,10 @@ start: bts ax, 0 mov cr0, eax - jmp 0x18:.mode32 + jmp 0x08:.mode32 bits 32 .mode32: - mov ax, 0x20 + mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax diff --git a/stage2.map b/stage2.map index 6405917a..68d4efb5 100644 Binary files a/stage2.map and b/stage2.map differ diff --git a/stage2/entry.asm b/stage2/entry.asm index c2b94a97..d7503160 100644 --- a/stage2/entry.asm +++ b/stage2/entry.asm @@ -1,6 +1,7 @@ extern bss_begin extern bss_end extern entry +extern gdt section .entry @@ -15,4 +16,14 @@ _start: sub ecx, bss_begin rep stosb + lgdt [gdt] + jmp 0x18:.reload_cs + .reload_cs: + mov eax, 0x20 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + jmp entry diff --git a/stage2/lib/part.c b/stage2/lib/part.c index b8d326ed..d54054a4 100644 --- a/stage2/lib/part.c +++ b/stage2/lib/part.c @@ -199,7 +199,7 @@ load_up: if (part_index) return; - part_index = conv_mem_alloc(sizeof(struct part) * part_count); + part_index = ext_mem_alloc(sizeof(struct part) * part_count); goto load_up; } } diff --git a/stage2/main.c b/stage2/main.c index 25d0ebe1..c741f7f3 100644 --- a/stage2/main.c +++ b/stage2/main.c @@ -33,10 +33,11 @@ void entry(uint8_t _boot_drive, int pxe_boot) { if (!a20_enable()) panic("Could not enable A20 line"); - part_create_index(); init_e820(); init_memmap(); + part_create_index(); + if (pxe_boot) { pxe_init(); if(init_config_pxe()) { diff --git a/stage2/mm/pmm.c b/stage2/mm/pmm.c index b0e83565..530ef8d5 100644 --- a/stage2/mm/pmm.c +++ b/stage2/mm/pmm.c @@ -293,13 +293,8 @@ void *conv_mem_alloc(size_t count) { void *conv_mem_alloc_aligned(size_t count, size_t alignment) { if (!bump_allocator_limit) { - // The balloc limit is the beginning of the GDT - struct { - uint16_t limit; - uint32_t ptr; - } __attribute__((packed)) gdtr; - asm volatile ("sgdt %0" :: "m"(gdtr) : "memory"); - bump_allocator_limit = gdtr.ptr; + // The balloc limit is the beginning of the EBDA + bump_allocator_limit = *((uint16_t *)0x40e) << 4; } size_t new_base = ALIGN_UP(bump_allocator_base, alignment); diff --git a/stage2/sys/gdt.asm b/stage2/sys/gdt.asm new file mode 100644 index 00000000..b9f450c5 --- /dev/null +++ b/stage2/sys/gdt.asm @@ -0,0 +1,63 @@ +section .data + +global gdt + +gdt: + dw .size - 1 ; GDT size + dd .start ; GDT start address + + .start: + ; Null desc + dq 0 + + ; 16-bit code + dw 0xffff ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10011010b ; Access + db 00000000b ; Granularity + db 0x00 ; Base (high 8 bits) + + ; 16-bit data + dw 0xffff ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10010010b ; Access + db 00000000b ; Granularity + db 0x00 ; Base (high 8 bits) + + ; 32-bit code + dw 0xffff ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10011010b ; Access + db 11001111b ; Granularity + db 0x00 ; Base (high 8 bits) + + ; 32-bit data + dw 0xffff ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10010010b ; Access + db 11001111b ; Granularity + db 0x00 ; Base (high 8 bits) + + ; 64-bit code + dw 0x0000 ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10011010b ; Access + db 00100000b ; Granularity + db 0x00 ; Base (high 8 bits) + + ; 64-bit data + dw 0x0000 ; Limit + dw 0x0000 ; Base (low 16 bits) + db 0x00 ; Base (mid 8 bits) + db 10010010b ; Access + db 00000000b ; Granularity + db 0x00 ; Base (high 8 bits) + + .end: + + .size: equ .end - .start