diff --git a/Makefile b/Makefile index 72c83ef1..eccd6b39 100644 --- a/Makefile +++ b/Makefile @@ -119,5 +119,5 @@ iso9660-test: | test-clean test.hdd bootloader all rm -rf test_image/ mkdir -p test_image/boot cp -rv bin/* test/* test_image/boot/ - genisoimage -no-emul-boot -b boot/limine-cd.bin -o test.iso test_image/ + genisoimage -no-emul-boot -b boot/limine-cd.bin -boot-load-size 4 -boot-info-table -o test.iso test_image/ qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -cdrom test.iso -debugcon stdio diff --git a/stage1/cd/bootsect.asm b/stage1/cd/bootsect.asm index 69d346fc..2965adb5 100644 --- a/stage1/cd/bootsect.asm +++ b/stage1/cd/bootsect.asm @@ -1,23 +1,24 @@ BITS 16 ORG 0x7C00 -; Please read bootsect/bootsect.asm before this file - -%define ISO9660_BUFFER 0x8000 -%define ROOT_DIRECTORY 156 -%define ROOT_DIRECTORY_BUFFER (ISO9660_BUFFER + ROOT_DIRECTORY) - -%define DIRECTORY_RECORD_LENGTH 0 -%define DIRECTORY_RECORD_LBA 2 -%define DIRECTORY_RECORD_SIZE 10 -%define DIRECTORY_RECORD_FILENAME_LENGTH 32 -%define DIRECTORY_RECORD_FILENAME 33 - +%define STAGE2_LOCATION 0x60000 +%define DECOMPRESSOR_LOCATION 0x70000 %define BOOT_FROM_CD 2 jmp skip_bpb nop -times 87 db 0 + +; El Torito Boot Information Table +; ↓ Set by mkisofs +times 8-($-$$) db 0 +boot_info: + bi_PVD dd 0 + bi_boot_LBA dd 0 + bi_boot_len dd 0 + bi_checksum dd 0 + bi_reserved times 40 db 0 + +times 90-($-$$) db 0 skip_bpb: cli @@ -41,31 +42,24 @@ skip_bpb: mov esp, 0x7C00 - ; --- Load the stage 2 --- - ; Find and load the PVD - call findPVD - jc err - - ; Load the root directory - mov eax, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_LBA] - mov ecx, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_SIZE] - - mov esi, ecx ; Size, for read_file - add ecx, 2047 - shr ecx, 11 + ; --- Load the decompressor --- + mov eax, dword [bi_boot_LBA] + add eax, DEC_LBA_OFFSET + mov ecx, DEC_LBA_COUNT + ; DECOMPRESSOR_LOCATION = 0x70000 = 0x7000:0x0000 + mov si, 0x7000 + xor di, di call read_2k_sectors jc err - ; Find and load '/BOOT' - mov ebx, TXT_BOOT - mov cl, TXT_BOOT_SZ - call read_file - jc err - - ; Find and load '/BOOT/LIMINE.SYS' - mov ebx, TXT_LIMINE - mov cl, TXT_LIMINE_SZ - call read_file ; esi is set from the last call + ; --- Load the stage2.bin.gz --- + mov eax, dword [bi_boot_LBA] + add eax, STAGE2_LBA_OFFSET + mov ecx, STAGE2_LBA_COUNT + ; STAGE2_LOCATION = 0x60000 = 0x6000:0x0000 + mov si, 0x6000 + xor di, di + call read_2k_sectors jc err ; Enable GDT @@ -81,7 +75,7 @@ err: hlt jmp err -%include 'iso9660.asm' +%include 'read_2k_sectors.asm' %include '../gdt.asm' BITS 32 @@ -93,17 +87,28 @@ pmode: mov gs, ax mov ss, ax - ; Time to handle control over to the stage 2 + ; Time to handle control over to the decompressor push BOOT_FROM_CD and edx, 0xFF push edx ; Boot drive - call ISO9660_BUFFER + push STAGE2_SIZE + push STAGE2_LOCATION + call DECOMPRESSOR_LOCATION hlt -TXT_BOOT: db "BOOT" -TXT_BOOT_SZ equ $ - TXT_BOOT -TXT_LIMINE: db "LIMINE.SYS;1" -TXT_LIMINE_SZ equ $ - TXT_LIMINE +%define FILEPOS ($-$$) +%define UPPER2K ((FILEPOS+2047) & ~2047) +%define ALIGN2K times UPPER2K - FILEPOS db 0 -; Just making sure the entry point (ISO9660_BUFFER) is not reached -times (0x8000 - 0x7C00) - ($ - $$) db 0 +; Align stage2 to 2K ON DISK +ALIGN2K +DEC_LBA_OFFSET equ ($-$$)/2048 +incbin '../../decompressor/decompressor.bin' + +ALIGN2K +STAGE2_START equ $-$$ +STAGE2_LBA_OFFSET equ STAGE2_START/2048 +DEC_LBA_COUNT equ STAGE2_LBA_OFFSET - DEC_LBA_OFFSET +incbin '../../stage23/stage2.bin.gz' +STAGE2_SIZE equ ($-$$) - STAGE2_START +STAGE2_LBA_COUNT equ (2047 + $-$$)/2048 diff --git a/stage1/cd/findFile.asm b/stage1/cd/findFile.asm deleted file mode 100644 index 0a66a2d1..00000000 --- a/stage1/cd/findFile.asm +++ /dev/null @@ -1,58 +0,0 @@ -BITS 16 - -; --- Find file in directory --- -; IN: -; eax <- directory extent -; ebx <- ptr to filename -; cl <- filename sz -; esi <- size of directory extent - -; OUT: -; eax <- LBA of the extent -; ebx <- size in bytes -; Carry if not found - -; SMASHES: -; ch -findFile: - push edx - push edi - push esi - mov edx, eax - - .checkEntry: - ; Get the size of this entry - mov edi, dword [edx + DIRECTORY_RECORD_LENGTH] - and edi, 0xFF - - ; Check filename size - mov al, byte [edx + DIRECTORY_RECORD_FILENAME_LENGTH] - cmp al, cl - jnz .gonext - - ; Sizes match, check filename - lea eax, dword [edx + DIRECTORY_RECORD_FILENAME] - call strcmp - jnc .found - - ; Go to the next - .gonext: - add edx, edi - sub esi, edi - test esi, esi - jnz .checkEntry - - .notfound: - stc - jmp .end - .found: - clc - mov eax, [edx + DIRECTORY_RECORD_LBA] - mov ebx, [edx + DIRECTORY_RECORD_SIZE] - .end: - pop esi - pop edi - pop edx - ret - -%include 'strcmp.asm' diff --git a/stage1/cd/findPVD.asm b/stage1/cd/findPVD.asm deleted file mode 100644 index 6f9b94d2..00000000 --- a/stage1/cd/findPVD.asm +++ /dev/null @@ -1,51 +0,0 @@ -BITS 16 - -; --- Find primary volume descriptor --- -; IN: -; dl <- drive number - -; OUT: -; [ISO9660_BUFFER] <- PVD -; Carry if not found -findPVD: - pusha - ; Just start reading volume descriptors - - mov eax, 0x10 ; First volume descriptor's LBA - .checkVD: - mov cx, 1 ; Each volume descriptor is 2KB - call read_2k_sectors - - ; Check identifier - mov ecx, ISO9660_BUFFER - inc ecx - mov bl, byte [ecx] - inc ecx - mov ecx, dword [ecx] - cmp bl, 'C' - jne .notfound - cmp ecx, 0x31303044 - jne .notfound - - ; Check type = 0xFF (final) - mov ecx, ISO9660_BUFFER - mov bl, byte [ecx] - cmp bl, 0xFF - jz .notfound - - ; Check type = 0x01 (PVD) - cmp bl, 0x01 - jz .found - - ; Didn't match, go to the next - inc eax - jmp .checkVD - - .found: - clc - jmp .end - .notfound: - stc - .end: - popa - ret diff --git a/stage1/cd/iso9660.asm b/stage1/cd/iso9660.asm deleted file mode 100644 index 28f1551f..00000000 --- a/stage1/cd/iso9660.asm +++ /dev/null @@ -1,35 +0,0 @@ -BITS 16 - -%include 'read_2k_sectors.asm' -%include 'findPVD.asm' -%include 'findFile.asm' - -; --- Read file --- -; IN: -; ebx <- ptr to filename -; cl <- filename sz -; esi <- size of directory extent - -; OUT: -; If found: [ISO9660_BUFFER] <- contents of the file -; If not found: CF=1 -; esi <- size in bytes - -; SMASHES: -; eax, ebx, ecx -read_file: - mov eax, ISO9660_BUFFER - call findFile - jc .end - - ; LBA of the extent is now @ eax - ; ebx is size in bytes - mov esi, ebx ; Return value - - ; bytes to 2k sectors - mov ecx, ebx - add ecx, 2047 - shr ecx, 11 - call read_2k_sectors - .end: - ret diff --git a/stage1/cd/read_2k_sectors.asm b/stage1/cd/read_2k_sectors.asm index f5d3dd16..7ebd0ba5 100644 --- a/stage1/cd/read_2k_sectors.asm +++ b/stage1/cd/read_2k_sectors.asm @@ -6,6 +6,8 @@ BITS 16 ; cx <- number of 2k sectors ; dl <- drive number ; ds <- ZERO +; di <- buffer offset +; si <- buffer segment ; OUT: ; Carry if error @@ -15,13 +17,16 @@ dapack: dapack_size: db 0x10 dapack_null: db 0x00 dapack_nblocks: dw 0 - dapack_buffer: dd ISO9660_BUFFER + dapack_offset: dw 0 + dapack_segment: dw 0 dapack_LBA: dq 0 read_2k_sectors: pusha mov dword [dapack_LBA], eax mov word [dapack_nblocks], cx + mov word [dapack_offset], di + mov word [dapack_segment], si mov ah, 0x42 mov si, dapack diff --git a/stage1/cd/strcmp.asm b/stage1/cd/strcmp.asm deleted file mode 100644 index fd21186f..00000000 --- a/stage1/cd/strcmp.asm +++ /dev/null @@ -1,34 +0,0 @@ -BITS 16 - -; --- Compare strings --- -; IN: -; eax <- ptr to first string -; ebx <- ptr to second string -; cl <- size of BOTH strings (must be the same) - -; OUT: -; CF=0 if equal, CF=1 otherwise -strcmp: - pusha - .nextchar: - mov dh, byte [eax] - mov dl, byte [ebx] - cmp dh, dl - jnz .notequal - - ; Characters match - dec cl - test cl, cl - jz .equal - inc eax - inc ebx - jmp .nextchar - - .equal: - clc - jmp .end - .notequal: - stc - .end: - popa - ret diff --git a/stage23/fs/file.c b/stage23/fs/file.c index 016532cd..8fbc65c4 100644 --- a/stage23/fs/file.c +++ b/stage23/fs/file.c @@ -24,7 +24,7 @@ bool fs_get_guid(struct guid *guid, struct volume *part) { int fopen(struct file_handle *ret, struct volume *part, const char *filename) { ret->is_memfile = false; - if (stage3_loaded && iso9660_check_signature(part)) { + if (iso9660_check_signature(part)) { struct iso9660_file_handle *fd = ext_mem_alloc(sizeof(struct iso9660_file_handle)); int r = iso9660_open(fd, part, filename); diff --git a/stage23/fs/iso9660.c b/stage23/fs/iso9660.c index 978ef1c8..4bfc9198 100644 --- a/stage23/fs/iso9660.c +++ b/stage23/fs/iso9660.c @@ -72,9 +72,9 @@ struct iso9660_contexts_node { struct iso9660_context context; struct iso9660_contexts_node *next; }; -stage3_data struct iso9660_contexts_node *contexts = NULL; +struct iso9660_contexts_node *contexts = NULL; -stage3_text static void iso9660_find_PVD(struct iso9660_volume_descriptor *desc, struct volume *vol) { +static void iso9660_find_PVD(struct iso9660_volume_descriptor *desc, struct volume *vol) { uint32_t lba = ISO9660_FIRST_VOLUME_DESCRIPTOR; while (true) { volume_read(vol, desc, lba * ISO9660_SECTOR_SIZE, ISO9660_SECTOR_SIZE); @@ -91,7 +91,7 @@ stage3_text static void iso9660_find_PVD(struct iso9660_volume_descriptor *desc, } } -stage3_text static void iso9660_cache_root(struct volume *vol, +static void iso9660_cache_root(struct volume *vol, void **root, uint32_t *root_size) { struct iso9660_primary_volume pv; @@ -102,7 +102,7 @@ stage3_text static void iso9660_cache_root(struct volume *vol, volume_read(vol, *root, pv.root.extent.little * ISO9660_SECTOR_SIZE, *root_size); } -stage3_text static struct iso9660_context *iso9660_get_context(struct volume *vol) { +static struct iso9660_context *iso9660_get_context(struct volume *vol) { struct iso9660_contexts_node *current = contexts; while (current) { if (current->context.vol.drive == vol->drive) @@ -120,7 +120,7 @@ stage3_text static struct iso9660_context *iso9660_get_context(struct volume *vo return &node->context; } -stage3_text static int iso9660_strcmp(const char *a, const char *b, size_t size) { +static int iso9660_strcmp(const char *a, const char *b, size_t size) { while (size--) { char ca = *a++; char cb = *b++; @@ -131,7 +131,7 @@ stage3_text static int iso9660_strcmp(const char *a, const char *b, size_t size) return 0; } -stage3_text static struct iso9660_directory_entry *iso9660_find(void *buffer, uint32_t size, const char *filename) { +static struct iso9660_directory_entry *iso9660_find(void *buffer, uint32_t size, const char *filename) { // The file can be either FILENAME or FILENAME;1 uint32_t len = strlen(filename); char finalfile[len + 2]; @@ -160,7 +160,7 @@ stage3_text static struct iso9660_directory_entry *iso9660_find(void *buffer, ui // --- Public functions --- -stage3_text int iso9660_check_signature(struct volume *vol) { +int iso9660_check_signature(struct volume *vol) { char buf[6]; const uint64_t signature = ISO9660_FIRST_VOLUME_DESCRIPTOR * ISO9660_SECTOR_SIZE + 1; volume_read(vol, buf, signature, 5); @@ -168,7 +168,7 @@ stage3_text int iso9660_check_signature(struct volume *vol) { return !strcmp(buf, "CD001"); } -stage3_text int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol, const char *path) { +int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol, const char *path) { ret->context = iso9660_get_context(vol); while (*path == '/') @@ -207,7 +207,7 @@ stage3_text int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol return 0; } -stage3_text int iso9660_read(struct iso9660_file_handle *file, void *buf, uint64_t loc, uint64_t count) { +int iso9660_read(struct iso9660_file_handle *file, void *buf, uint64_t loc, uint64_t count) { volume_read(&file->context->vol, buf, file->LBA * ISO9660_SECTOR_SIZE + loc, count); return 0; } diff --git a/stage23/main.c b/stage23/main.c index 76e7cc84..3086488c 100644 --- a/stage23/main.c +++ b/stage23/main.c @@ -31,7 +31,6 @@ void entry(uint8_t _boot_drive, int boot_from) { booted_from_pxe = (boot_from == BOOT_FROM_PXE); booted_from_cd = (boot_from == BOOT_FROM_CD); - stage3_loaded = booted_from_cd; // CD loads both stages mtrr_save();