flat assembler
Message board for the users of flat assembler.
![]() |
Author |
|
bzt 17 Oct 2024, 18:42
Hi,
If someone needs this, I've implemented a little hack to make BIOS boot loaders work with ISO9660 El Torito "no emulation" mode. The issue they are facing is, that BIOS assumes sector sizes to be 512 bytes always, except for CDs, where the sector size is 2048 bytes, therefore the LBA addressing is messed up (and could lead to potential buffer overflows as well). How does this work? Normally the disk has some partitioning table which points to the first sectors of partitions (legacy MBR or GPT). With El Torito, there's a so called Boot Catalog, which does the same, it points to some sectors, and when booted from a CDROM, this catalog is used instead of the partitioning table. Now because of UEFI spec section 12.3.2.1, in order to boot from CDROM under EFI, the Boot Catalog must point to the same EFI System Partition's first sector (VBR, Volume Boot Record) where normally a GPT entry points. Under EFI this VBR is never executed and contains no code at all, it's just a FAT's first sector with BPB data. On the other hand, the BIOS in El Torito mode loads and executes this VBR. (Worth noting that the Boot Catalog should have a separate entry for BIOS boot sector and EFI ESP first sector, however because of TianoCore based buggy firmware this separation doesn't seem to work at all, both selects the same entry). So this code should be installed in the ESP's VBR sector where the Boot Catalog points to and which is only executed when booted under BIOS in El Torito mode. This code hooks INT 13h and emulates a secondary HDD with 512 bytes sectors. It then loads the very first MBR sector of the CDROM to 7C00h and jumps to it. The MBR code then works as usual, it doesn't have to care about different sector sizes. This solution works with any kinds of boot loader. Summary: - Normal flow: BIOS loads MBR -> MBR parses partitioning table loads VBR - This hack: BIOS parses Boot Catalog loads VBR -> VBR loads MBR (and after that business as usual) Limitations: - requires 80386 at least (beacuse I was lazy and used edx to store the LBA) - limited to 32-bit LBA addresses (not an issue with CDROMs / DVDs) cdemu_x86.asm Code: ; cdemu_x86.asm ; Copyright (C) 2024 bzt, MIT license ; ; Memory layout on handover: ; 0h - 400h IVT (must be preserved) ; 400h - 7C00h stack ; 7C00h - 7E00h we're loaded here, also original MBR loaded here ; 9A000h - 9A200h our relocated TSR code ; 9A200h - 9AA00h CDROM sector cache SEG equ 09A00h ORG 0h USE16 virtual at 0 lbapacket.size: dw ? lbapacket.count:dw ? lbapacket.addr0:dw ? lbapacket.addr1:dw ? lbapacket.sect0:dw ? lbapacket.sect1:dw ? lbapacket.sect2:dw ? lbapacket.sect3:dw ? end virtual ;********************************************************************* ;* data area * ;********************************************************************* ;could be 0:7C00 or 07C0:0 as well depending on BIOS lbapacket: jmp short @f ; mandatory jump (magic) nop db 13 dup 0 origip: dw 0 origcs: dw 0 save: dd 0 drive: dw 0 db 060h-($-$$) dup 0 ; skip over FAT32 BPB ;********************************************************************* ;* code * ;********************************************************************* @@: cli cld xor ax, ax mov ss, ax mov sp, 07C00h ;find our position in memory. push cs pop ds call @f @@: pop si sub si, @b-lbapacket ;---- relocate ourself to 09A00:0000 ---- mov ax, SEG mov es, ax xor di, di mov cx, 200h repnz movsw push es pop ds jmp SEG:.start ;clear and reuse BPB data area .start: xor di, di xor ax, ax mov cx, 30h repnz stosw mov byte [drive], dl ; save CDROM's drive code xor di, di mov al, 16 ; .size stosw mov al, 1 ; .count stosw mov ax, cache ; .addr0 push ax stosw mov ax, es ; .addr1 stosw ;load the original MBR (plus 3 more sectors) into cache mov ah, byte 42h xor si, si int 13h ;copy the first 512 bytes of cache to 0:7C00h pop si mov di, sp push es xor ax, ax mov es, ax mov cx, 100h repnz movsw pop es ;---- install TSR, hook INT 13h ---- mov di, origip xor ax, ax mov ds, ax mov si, 13h * 4 mov ax, word[si] stosw mov word[si], tsr add si, 2 mov ax, word[si] stosw mov ax, es mov word[si], ax ;---- arrange environment and jump to MBR code ---- xor ax, ax mov es, ax mov bx, ax mov cx, ax mov dx, ax mov si, ax mov di, ax mov dl, 81h ; secondary BIOS HDD mov ax, 0AA55h jmp 0:7C00h ;---- emulate 2048 bytes CDROM sectors as 512 bytes HDD sectors ---- tsr: ;pass through all non "extended read on secondary HDD" calls cmp ah, 42h jne @f cmp dl, 81h je .emulate @@: jmp dword[cs:origip] .emulate: push es push ds push cx push dx push si ;read the lba packet we're servicing into registers mov di, word [si + lbapacket.addr0] mov ax, word [si + lbapacket.addr1] mov es, ax xor bh, bh mov bl, byte [si + lbapacket.count] mov edx, dword [si + lbapacket.sect0] push cs pop ds or bl, bl jz .none ;---- for each sector ---- .next: ;do we have the relevant 2048 bytes sector cached? mov eax, edx shr eax, 2 cmp eax, dword[lbapacket.sect0] je @f ;no, read it in from CDROM push es push ds push di push bx mov dword[save], edx ;call original ISR mov dword[lbapacket.sect0], eax mov dl, byte[drive] mov ax, 4200h xor si, si clc pushf call dword[origip] mov edx, dword[save] pop bx pop di pop ds pop es jc .end or ah, ah jnz .end ;copy 512 bytes from cache to caller's buffer @@: mov si, dx and si, 3 shl si, 9 add si, cache mov cx, 100h repnz movsw ;adjust to next sector inc edx inc bh dec bl or bl, bl jnz .next ;---- finished ---- .none: xor ax, ax clc .end: pop si pop dx pop cx pop ds pop es ;update the sector count in caller's lba packet mov byte[si + lbapacket.count], bh mov bx, 0AA55h iret ;padding (check if our code fits into 510 bytes) db 01FEh-($-$$) dup 0 db 55h, 0AAh ; mandatory magic bytes ;********************************************************************* ;* bss area * ;********************************************************************* cache: db 2048 dup ? ; CDROM sector cache Hope this going to be useful, bzt |
|||
![]() |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.