iso9660: back to stage2+decompressor

This commit is contained in:
JlXip 2021-02-25 01:40:02 +01:00
parent 1a5cb00cda
commit 7677c6109d
10 changed files with 66 additions and 235 deletions

View File

@ -119,5 +119,5 @@ iso9660-test: | test-clean test.hdd bootloader all
rm -rf test_image/ rm -rf test_image/
mkdir -p test_image/boot mkdir -p test_image/boot
cp -rv bin/* test/* 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 qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -cdrom test.iso -debugcon stdio

View File

@ -1,23 +1,24 @@
BITS 16 BITS 16
ORG 0x7C00 ORG 0x7C00
; Please read bootsect/bootsect.asm before this file %define STAGE2_LOCATION 0x60000
%define DECOMPRESSOR_LOCATION 0x70000
%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 BOOT_FROM_CD 2 %define BOOT_FROM_CD 2
jmp skip_bpb jmp skip_bpb
nop 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: skip_bpb:
cli cli
@ -41,31 +42,24 @@ skip_bpb:
mov esp, 0x7C00 mov esp, 0x7C00
; --- Load the stage 2 --- ; --- Load the decompressor ---
; Find and load the PVD mov eax, dword [bi_boot_LBA]
call findPVD add eax, DEC_LBA_OFFSET
jc err mov ecx, DEC_LBA_COUNT
; DECOMPRESSOR_LOCATION = 0x70000 = 0x7000:0x0000
; Load the root directory mov si, 0x7000
mov eax, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_LBA] xor di, di
mov ecx, dword [ROOT_DIRECTORY_BUFFER + DIRECTORY_RECORD_SIZE]
mov esi, ecx ; Size, for read_file
add ecx, 2047
shr ecx, 11
call read_2k_sectors call read_2k_sectors
jc err jc err
; Find and load '/BOOT' ; --- Load the stage2.bin.gz ---
mov ebx, TXT_BOOT mov eax, dword [bi_boot_LBA]
mov cl, TXT_BOOT_SZ add eax, STAGE2_LBA_OFFSET
call read_file mov ecx, STAGE2_LBA_COUNT
jc err ; STAGE2_LOCATION = 0x60000 = 0x6000:0x0000
mov si, 0x6000
; Find and load '/BOOT/LIMINE.SYS' xor di, di
mov ebx, TXT_LIMINE call read_2k_sectors
mov cl, TXT_LIMINE_SZ
call read_file ; esi is set from the last call
jc err jc err
; Enable GDT ; Enable GDT
@ -81,7 +75,7 @@ err:
hlt hlt
jmp err jmp err
%include 'iso9660.asm' %include 'read_2k_sectors.asm'
%include '../gdt.asm' %include '../gdt.asm'
BITS 32 BITS 32
@ -93,17 +87,28 @@ pmode:
mov gs, ax mov gs, ax
mov ss, 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 push BOOT_FROM_CD
and edx, 0xFF and edx, 0xFF
push edx ; Boot drive push edx ; Boot drive
call ISO9660_BUFFER push STAGE2_SIZE
push STAGE2_LOCATION
call DECOMPRESSOR_LOCATION
hlt hlt
TXT_BOOT: db "BOOT" %define FILEPOS ($-$$)
TXT_BOOT_SZ equ $ - TXT_BOOT %define UPPER2K ((FILEPOS+2047) & ~2047)
TXT_LIMINE: db "LIMINE.SYS;1" %define ALIGN2K times UPPER2K - FILEPOS db 0
TXT_LIMINE_SZ equ $ - TXT_LIMINE
; Just making sure the entry point (ISO9660_BUFFER) is not reached ; Align stage2 to 2K ON DISK
times (0x8000 - 0x7C00) - ($ - $$) db 0 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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -6,6 +6,8 @@ BITS 16
; cx <- number of 2k sectors ; cx <- number of 2k sectors
; dl <- drive number ; dl <- drive number
; ds <- ZERO ; ds <- ZERO
; di <- buffer offset
; si <- buffer segment
; OUT: ; OUT:
; Carry if error ; Carry if error
@ -15,13 +17,16 @@ dapack:
dapack_size: db 0x10 dapack_size: db 0x10
dapack_null: db 0x00 dapack_null: db 0x00
dapack_nblocks: dw 0 dapack_nblocks: dw 0
dapack_buffer: dd ISO9660_BUFFER dapack_offset: dw 0
dapack_segment: dw 0
dapack_LBA: dq 0 dapack_LBA: dq 0
read_2k_sectors: read_2k_sectors:
pusha pusha
mov dword [dapack_LBA], eax mov dword [dapack_LBA], eax
mov word [dapack_nblocks], cx mov word [dapack_nblocks], cx
mov word [dapack_offset], di
mov word [dapack_segment], si
mov ah, 0x42 mov ah, 0x42
mov si, dapack mov si, dapack

View File

@ -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

View File

@ -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) { int fopen(struct file_handle *ret, struct volume *part, const char *filename) {
ret->is_memfile = false; 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)); struct iso9660_file_handle *fd = ext_mem_alloc(sizeof(struct iso9660_file_handle));
int r = iso9660_open(fd, part, filename); int r = iso9660_open(fd, part, filename);

View File

@ -72,9 +72,9 @@ struct iso9660_contexts_node {
struct iso9660_context context; struct iso9660_context context;
struct iso9660_contexts_node *next; 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; uint32_t lba = ISO9660_FIRST_VOLUME_DESCRIPTOR;
while (true) { while (true) {
volume_read(vol, desc, lba * ISO9660_SECTOR_SIZE, ISO9660_SECTOR_SIZE); 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, void **root,
uint32_t *root_size) { uint32_t *root_size) {
struct iso9660_primary_volume pv; 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); 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; struct iso9660_contexts_node *current = contexts;
while (current) { while (current) {
if (current->context.vol.drive == vol->drive) 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; 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--) { while (size--) {
char ca = *a++; char ca = *a++;
char cb = *b++; char cb = *b++;
@ -131,7 +131,7 @@ stage3_text static int iso9660_strcmp(const char *a, const char *b, size_t size)
return 0; 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 // The file can be either FILENAME or FILENAME;1
uint32_t len = strlen(filename); uint32_t len = strlen(filename);
char finalfile[len + 2]; char finalfile[len + 2];
@ -160,7 +160,7 @@ stage3_text static struct iso9660_directory_entry *iso9660_find(void *buffer, ui
// --- Public functions --- // --- Public functions ---
stage3_text int iso9660_check_signature(struct volume *vol) { int iso9660_check_signature(struct volume *vol) {
char buf[6]; char buf[6];
const uint64_t signature = ISO9660_FIRST_VOLUME_DESCRIPTOR * ISO9660_SECTOR_SIZE + 1; const uint64_t signature = ISO9660_FIRST_VOLUME_DESCRIPTOR * ISO9660_SECTOR_SIZE + 1;
volume_read(vol, buf, signature, 5); volume_read(vol, buf, signature, 5);
@ -168,7 +168,7 @@ stage3_text int iso9660_check_signature(struct volume *vol) {
return !strcmp(buf, "CD001"); 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); ret->context = iso9660_get_context(vol);
while (*path == '/') while (*path == '/')
@ -207,7 +207,7 @@ stage3_text int iso9660_open(struct iso9660_file_handle *ret, struct volume *vol
return 0; 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); volume_read(&file->context->vol, buf, file->LBA * ISO9660_SECTOR_SIZE + loc, count);
return 0; return 0;
} }

View File

@ -31,7 +31,6 @@ void entry(uint8_t _boot_drive, int boot_from) {
booted_from_pxe = (boot_from == BOOT_FROM_PXE); booted_from_pxe = (boot_from == BOOT_FROM_PXE);
booted_from_cd = (boot_from == BOOT_FROM_CD); booted_from_cd = (boot_from == BOOT_FROM_CD);
stage3_loaded = booted_from_cd; // CD loads both stages
mtrr_save(); mtrr_save();