Hi! I tried to keep the BIOS functionality as most as possible. There is function _pci16_function located at the offset 0x908a. To keep it working I reassembled the code of this function and cutted off a code branch that have very little chances to be executed. That branch checks for the size of submitted buffer by PCI driver and terminates the rest of execution in case of insufficient buffer size. In normal situation this will never happens. Also note that this code used only for 16-bit native drivers. I wrote about that in my previuos message. The code marked by red is removed in modified BIOS. Code: void BIOSCALL PCIxx(function)(volatile pci_regs_t r) { pci_route_buf __far *route_buf; uint16_t device; SET_AH(SUCCESSFUL); /* Assume success. */ CLEAR_CF(); switch (GET_AL()) { case PCI_BIOS_PRESENT: AX = 0x0001; /* Configuration mechanism #1 supported. */ BX = 0x0210; /* Version 2.1. */ //@todo: return true max bus # in CL CX = 0; /* Maximum bus number. */ EDX = 'P' | ('C' << 8) | ((uint32_t)'I' << 16) | ((uint32_t)' ' << 24); break; case FIND_PCI_DEVICE: /* Vendor ID FFFFh is reserved so that non-present devices can * be easily detected. */ if (DX == 0xFFFF) { SET_AH(BAD_VENDOR_ID); SET_CF(); } else { device = PCIxx(find_device)(DX | (uint32_t)CX << 16, SI, 0); if (device == BUSDEVFN_NOT_FOUND) { SET_AH(DEVICE_NOT_FOUND); SET_CF(); } else { BX = device; } } break; case FIND_PCI_CLASS_CODE: device = PCIxx(find_device)(ECX, SI, 1); if (device == BUSDEVFN_NOT_FOUND) { SET_AH(DEVICE_NOT_FOUND); SET_CF(); } else { BX = device; } break; case READ_CONFIG_BYTE: case READ_CONFIG_WORD: case READ_CONFIG_DWORD: case WRITE_CONFIG_BYTE: case WRITE_CONFIG_WORD: case WRITE_CONFIG_DWORD: if (DI >= 256) { SET_AH(BAD_REGISTER_NUMBER); SET_CF(); } else { PCIxx(select_reg)(BX, DI); switch (GET_AL()) { case READ_CONFIG_BYTE: SET_CL(inp(PCI_CFG_DATA + (DI & 3))); break; case READ_CONFIG_WORD: CX = inpw(PCI_CFG_DATA + (DI & 2)); break; case READ_CONFIG_DWORD: ECX = inpd(PCI_CFG_DATA); break; case WRITE_CONFIG_BYTE: outp(PCI_CFG_DATA + (DI & 3), GET_CL()); break; case WRITE_CONFIG_WORD: outpw(PCI_CFG_DATA + (DI & 2), CX); break; case WRITE_CONFIG_DWORD: outpd(PCI_CFG_DATA, ECX); break; } } break; case GET_IRQ_ROUTING: route_buf = ES :> (void *)DI; if (pci_routing_table_size > route_buf->buf_size) { SET_AH(BUFFER_TOO_SMALL); SET_CF(); } else { rep_movsb(route_buf->buf_ptr, pci_routing_table, pci_routing_table_size); /* IRQs 9 and 11 are PCI only. */ BX = (1 << 9) | (1 << 11); } route_buf->buf_size = pci_routing_table_size; break; default: BX_INFO("PCI: Unsupported function AX=%04X BX=%04X called\n", AX, BX); SET_AH(FUNC_NOT_SUPPORTED); SET_CF(); } } Asm code is below. Code of the specified function will clear description above. The "before" part is the code of original BIOS function and the "after" part is the code of modified BIOS function. I also rearranged some blocks to keep correctness of short jumps. Before: Code: _pci16_function: ; 0xf9016 LB 0x1d7 push bp ; 55 mov bp, sp ; 89 e5 push si ; 56 push di ; 57 push ax ; 50 push ax ; 50 and word [bp+020h], 000ffh ; 81 66 20 ff 00 and word [bp+02ch], strict byte 0fffeh ; 83 66 2c fe mov bx, word [bp+020h] ; 8b 5e 20 xor bh, bh ; 30 ff mov ax, word [bp+020h] ; 8b 46 20 xor ah, ah ; 30 e4 cmp bx, strict byte 00003h ; 83 fb 03 jc short 0904fh ; 72 1a jbe short 090a7h ; 76 70 cmp bx, strict byte 0000eh ; 83 fb 0e je near 09174h ; 0f 84 36 01 cmp bx, strict byte 00008h ; 83 fb 08 jc near 091b9h ; 0f 82 74 01 cmp bx, strict byte 0000dh ; 83 fb 0d jbe near 090cch ; 0f 86 80 00 jmp near 091b9h ; e9 6a 01 cmp bx, strict byte 00002h ; 83 fb 02 je short 09077h ; 74 23 cmp bx, strict byte 00001h ; 83 fb 01 jne near 091b9h ; 0f 85 5e 01 mov word [bp+020h], strict word 00001h ; c7 46 20 01 00 mov word [bp+014h], 00210h ; c7 46 14 10 02 mov word [bp+01ch], strict word 00000h ; c7 46 1c 00 00 mov word [bp+018h], 04350h ; c7 46 18 50 43 mov word [bp+01ah], 02049h ; c7 46 1a 49 20 jmp near 091e6h ; e9 6f 01 cmp word [bp+018h], strict byte 0ffffh ; 83 7e 18 ff jne short 09083h ; 75 06 or ah, 083h ; 80 cc 83 jmp near 091dfh ; e9 5c 01 mov bx, word [bp+008h] ; 8b 5e 08 mov dx, word [bp+01ch] ; 8b 56 1c mov ax, word [bp+018h] ; 8b 46 18 xor cx, cx ; 31 c9 call 08f1fh ; e8 8e fe cmp ax, strict word 0ffffh ; 3d ff ff jne short 090a1h ; 75 0b mov ax, word [bp+020h] ; 8b 46 20 xor ah, ah ; 30 e4 or ah, 086h ; 80 cc 86 jmp near 091dfh ; e9 3e 01 mov word [bp+014h], ax ; 89 46 14 jmp near 091e6h ; e9 3f 01 mov bx, word [bp+008h] ; 8b 5e 08 mov ax, word [bp+01ch] ; 8b 46 1c mov dx, word [bp+01eh] ; 8b 56 1e mov cx, strict word 00001h ; b9 01 00 call 08f1fh ; e8 69 fe cmp ax, strict word 0ffffh ; 3d ff ff jne short 090c6h ; 75 0b mov ax, word [bp+020h] ; 8b 46 20 xor ah, ah ; 30 e4 or ah, 086h ; 80 cc 86 jmp near 091dfh ; e9 19 01 mov word [bp+014h], ax ; 89 46 14 jmp near 091e6h ; e9 1a 01 cmp word [bp+004h], 00100h ; 81 7e 04 00 01 jc short 090d9h ; 72 06 or ah, 087h ; 80 cc 87 jmp near 091dfh ; e9 06 01 mov dx, word [bp+004h] ; 8b 56 04 mov ax, word [bp+014h] ; 8b 46 14 call 08efbh ; e8 19 fe mov bx, word [bp+020h] ; 8b 5e 20 xor bh, bh ; 30 ff sub bx, strict byte 00008h ; 83 eb 08 cmp bx, strict byte 00005h ; 83 fb 05 jnbe near 091e6h ; 0f 87 f5 00 add bx, bx ; 01 db jmp word [cs:bx-06ff6h] ; 2e ff a7 0a 90 mov bx, word [bp+01ch] ; 8b 5e 1c xor bl, bl ; 30 db mov dx, word [bp+004h] ; 8b 56 04 and dx, strict byte 00003h ; 83 e2 03 add dx, 00cfch ; 81 c2 fc 0c in AL, DX ; ec db 02ah, 0e4h ; sub ah, ah ; 2a e4 or bx, ax ; 09 c3 mov word [bp+01ch], bx ; 89 5e 1c jmp near 091e6h ; e9 d4 00 mov dx, word [bp+004h] ; 8b 56 04 xor dh, dh ; 30 f6 and dl, 002h ; 80 e2 02 add dx, 00cfch ; 81 c2 fc 0c in ax, DX ; ed mov word [bp+01ch], ax ; 89 46 1c jmp near 091e6h ; e9 c1 00 mov dx, 00cfch ; ba fc 0c in eax, DX ; 66 ed db 08bh, 0d0h ; mov dx, ax ; 8b d0 shr eax, 010h ; 66 c1 e8 10 xchg dx, ax ; 92 mov word [bp+01ch], ax ; 89 46 1c mov word [bp+01eh], dx ; 89 56 1e jmp near 091e6h ; e9 ac 00 mov ax, word [bp+01ch] ; 8b 46 1c mov dx, word [bp+004h] ; 8b 56 04 xor dh, dh ; 30 f6 and dl, 003h ; 80 e2 03 add dx, 00cfch ; 81 c2 fc 0c out DX, AL ; ee jmp near 091e6h ; e9 99 00 mov ax, word [bp+01ch] ; 8b 46 1c mov dx, word [bp+004h] ; 8b 56 04 xor dh, dh ; 30 f6 and dl, 002h ; 80 e2 02 add dx, 00cfch ; 81 c2 fc 0c out DX, ax ; ef jmp near 091e6h ; e9 86 00 mov ax, word [bp+01ch] ; 8b 46 1c mov cx, word [bp+01eh] ; 8b 4e 1e mov dx, 00cfch ; ba fc 0c xchg cx, ax ; 91 sal eax, 010h ; 66 c1 e0 10 db 08bh, 0c1h ; mov ax, cx ; 8b c1 out DX, eax ; 66 ef jmp short 091e6h ; eb 72 mov bx, word [bp+004h] ; 8b 5e 04 mov es, [bp+026h] ; 8e 46 26 mov word [bp-008h], bx ; 89 5e f8 mov [bp-006h], es ; 8c 46 fa mov cx, word [0f4a0h] ; 8b 0e a0 f4 cmp cx, word [es:bx] ; 26 3b 0f jbe short 0919ah ; 76 11 mov ax, word [bp+020h] ; 8b 46 20 xor ah, ah ; 30 e4 or ah, 089h ; 80 cc 89 mov word [bp+020h], ax ; 89 46 20 or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 jmp short 091aeh ; eb 14 les di, [es:bx+002h] ; 26 c4 7f 02 mov si, 0f2c0h ; be c0 f2 mov dx, ds ; 8c da push DS ; 1e mov ds, dx ; 8e da rep movsb ; f3 a4 pop DS ; 1f mov word [bp+014h], 00a00h ; c7 46 14 00 0a mov ax, word [0f4a0h] ; a1 a0 f4 les bx, [bp-008h] ; c4 5e f8 mov word [es:bx], ax ; 26 89 07 jmp short 091e6h ; eb 2d mov bx, 00da2h ; bb a2 0d mov cx, ds ; 8c d9 mov ax, strict word 00004h ; b8 04 00 call 018cch ; e8 08 87 mov ax, word [bp+014h] ; 8b 46 14 push ax ; 50 mov ax, word [bp+020h] ; 8b 46 20 push ax ; 50 push 00d5eh ; 68 5e 0d push strict byte 00004h ; 6a 04 call 0190dh ; e8 39 87 add sp, strict byte 00008h ; 83 c4 08 mov ax, word [bp+020h] ; 8b 46 20 xor ah, ah ; 30 e4 or ah, 081h ; 80 cc 81 mov word [bp+020h], ax ; 89 46 20 or word [bp+02ch], strict byte 00001h ; 83 4e 2c 01 lea sp, [bp-004h] ; 8d 66 fc pop di ; 5f pop si ; 5e pop bp ; 5d retn ; c3 After (note that labels named in "after" here used just as labels, it names does not correspond to real offset but in "before" it does): Code: _pci16_function: ; 0xf9016 LB 0x1d7 ; 0xf9016 push bp mov bp, sp push si push di push ax push ax and word [bp+20h], 0FFh and word [bp+02ch], strict byte 0fffeh mov bx, word [bp+020h] xor bh, bh mov ax, word [bp+20h] xor ah, ah cmp bx, strict byte 00003h jb short loc_F904F jbe short loc_F90A7 cmp bx, strict byte 0000eh jz loc_F9174 cmp bx, strict byte 00008h jb loc_F91DF cmp bx, strict byte 0000dh ;jbe loc_F90CC jmp short loc_F90D9 ;jmp loc_F91DF ; --------------------------------------------------------------------------- loc_F904F: ; ... cmp bx, strict byte 00002h jz short loc_F9077 cmp bx, strict byte 00001h jnz loc_F91DF mov word [bp+020h], strict word 00001h mov word [bp+14h], 210h mov word [bp+01ch], strict word 00000h mov word [bp+18h], 4350h mov word [bp+1Ah], 2049h jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F9077: ; ... cmp word [bp+018h], strict byte 0ffffh jnz short loc_F9083 or ah, 83h jmp loc_F91DF ; --------------------------------------------------------------------------- loc_F9083: ; ... mov bx, word [bp+008h] mov dx, word [bp+01ch] mov ax, word [bp+018h] xor cx, cx call 8F1Fh cmp ax, strict word 0ffffh jnz short loc_F90A1 mov ax, [bp+20h] xor ah, ah or ah, 86h jmp loc_F91DF ; --------------------------------------------------------------------------- loc_F90A1: ; ... mov [bp+14h], ax jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F90A7: ; ... mov bx, [bp+8] mov ax, [bp+1Ch] mov dx, [bp+1Eh] mov cx, strict word 00001h call 8F1Fh cmp ax, strict word 0ffffh jnz short loc_F90C6 mov ax, [bp+20h] xor ah, ah or ah, 86h jmp loc_F91DF ; --------------------------------------------------------------------------- loc_F90D9: ; ... mov dx, [bp+4] mov ax, [bp+14h] call 8EFBh mov bx, [bp+20h] xor bh, bh sub bx, strict byte 00008h cmp bx, strict byte 00005h ja loc_F91E6 add bx, bx jmp word [cs:bx-06ff6h] db 0h dd 'Windows_Virtual_XP_F9161D8E7FCC11DDBFAA369856D89593' dd 0h db 0h loc_F90C6: ; ... mov [bp+14h], ax jmp loc_F91E6 ; --------------------------------------------------------------------------- ;loc_F90CC: ; ... ;cmp word [bp+4], 100h ;jb short loc_F90D9 ;or ah, 87h ;jmp loc_F91DF ; --------------------------------------------------------------------------- loc_F90F8: ; ... mov bx, [bp+1Ch] xor bl, bl mov dx, [bp+4] and dx, strict byte 00003h add dx, 0CFCh in al, dx db 02ah, 0e4h ; sub ah, ah or bx, ax mov [bp+1Ch], bx jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F9112: ; ... mov dx, [bp+4] xor dh, dh and dl, 2 add dx, 0CFCh in ax, dx mov [bp+1Ch], ax jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F9125: ; ... mov dx, 0CFCh in eax, dx ; PCI Configuration Space Data Register db 08bh, 0d0h ; sub ah, ah shr eax, 10h xchg ax, dx mov [bp+1Ch], ax mov [bp+1Eh], dx jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F913A: ; ... mov ax, [bp+1Ch] mov dx, [bp+4] xor dh, dh and dl, 3 add dx, 0CFCh out dx, al jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F914D: ; ... mov ax, [bp+1Ch] mov dx, [bp+4] xor dh, dh and dl, 2 add dx, 0CFCh out dx, ax jmp loc_F91E6 ; --------------------------------------------------------------------------- loc_F9160: ; ... mov ax, [bp+1Ch] mov cx, [bp+1Eh] mov dx, 0CFCh xchg ax, cx shl eax, 10h db 08bh, 0c1h ; mov ax, cx out dx, eax ; PCI Configuration Space Data Register jmp short loc_F91E6 ; --------------------------------------------------------------------------- loc_F9174: ; ... mov bx, [bp+4] mov es, word [bp+26h] mov [bp-8], bx mov word [bp-6], es mov cx, word [0f4a0h] cmp cx, word [es:bx] jbe short loc_F919A mov ax, [bp+20h] xor ah, ah or ah, 89h mov [bp+20h], ax or word [bp+02ch], strict byte 00001h jmp short loc_F91AE ; --------------------------------------------------------------------------- loc_F919A: ; ... les di, [es:bx+002h] mov si, 0F2C0h mov dx, ds push ds mov ds, dx rep movsb pop ds mov word [bp+14h], 0A00h loc_F91AE: ; ... mov ax, word [0f4a0h] les bx, [bp-8] mov word [es:bx], ax jmp short loc_F91E6 ; --------------------------------------------------------------------------- loc_F91DF: ; ... mov [bp+20h], ax or word [bp+02ch], strict byte 00001h loc_F91E6: ; ... lea sp, [bp-4] pop di pop si pop bp retn ; 0xf91ed Also, the string Code: F000,908A,,Windows_Virtual_XP_F9161D8E7FCC11DDBFAA369856D89593 is equivalent to Code: F000,908A,104,Windows_Virtual_XP_F9161D8E7FCC11DDBFAA369856D89593 and 104 is also HEX, i.e. 0x104. It means that the string can be placed in 908A....918E and the offset I chose is valid.
All I can say is wow! You have clearly explained everything and you did more than I would have done... for future VBox releases, do you think the _pci16_function will remain the same so that you can reuse your hard work? Thanks for the clarification on the 104h as opposed to 104d. And lastly, forgive me for having this paranoia of a possible BIOS malware when I saw this: View attachment 26901 Left side is original 4.3.6 BIOS and right side is your hacked BIOS (using vimdiff)... I was scared by all that differences! Now I understand. So, just to confirm, you had to recompile VBoxDD2.[DLL|so] from sources with your modified _pci16_function right? Or maybe you just needed to recompile VBoxBiosAlternative.asm. Once again, awesome work! Further work on this matter, I tried another method: using Virtual PC's own BIOS... since it works perfectly with Windows XP Mode, I assumed that the OEM String is in the BIOS. I ran Resource Hacker on VPC.EXE and extracted the BIOS. It's 256K and a variation of AMIBIOS. I just loaded the BIOS in VirtualBox but the VM did not boot. Any ideas why it doesn't work? Can it work?
@nerd.brazil You can't use Virtual PC's bios in VirtualBox as they emulate totally different hardwares (like you can't flash Asus K53SC's bios in Asus K55VD).
XP mode activation I downloaded modified VirtualBox BIOS with added OEM SPL string for Windows XP mode (Windows_Virtual_XP_F9161D8E7FCC11DDBFAA369856D89593), but if I choose SATA controller VM crash. So I patched VirtualBox BIOS myself - It works fine when using extradata "VBoxInternal/Devices/pcbios/0/Config/BiosRom" in vbox config via command Code: VBoxManage setextradata "Windows XP" VBoxInternal/Devices/pcbios/0/Config/BiosRom "/path/to/xpbios.bin" SATA works fine! BIOS is from VirtualBox 4.2.16 on Ubuntu 13.10, SPL string (Windows_Virtual_XP_F9161D8E7FCC11DDBFAA369856D89593) is on offset 0x908A.
[h=2](pardon me for posting this as a new thread... didn't mean to) A few questions...[/h] I've seen many times people say to just insert the SLP string in the DMI area of BIOS, and when researching this matter I have a few questions: 1) Isn't DMI a soon-to-be deprecated syntax which is now being superceded by SMBIOS? 2) They perform similar function in that they provide hardware information to the OS right? 3) Is the SMBIOS/DMI region inside the BIOS ROM code? E.g. VirtualBox's BIOS is 64K in size; it's SMBIOS/DMI Entry Point Table is defined towards the end of the BIOS ROM at offset 0xFF60. It defines the DMI TableAddress to be 0x000E1000 which is outside the BIOS ROM area. I've read that the SMBIOS Tables is created elsewhere and thus I assume that the table is NOT inside the BIOS ROM. "dmidecode" informs that there is no DMI entries. What area is the SLP string stored then? Any place that is empty and free of code? People say DMI area... but I can't verify this. I understand that sometimes if the SLP string is expected within a wide address range, then adding the string to the XML config file could work. Not so for the Windows XP Mode string.
Forgive me if there's an obvious answer to this, but is there some advantage to using the "XP Mode" SLP string versus other SLP strings? XP will activate in virtualbox just fine by setting the DmiSystemVendor to Dell or Hewlett-Packard and using the corresponding OEMBIOS files for example. The only thing I can think of is that XP Mode looks more legitimate?
ailin, Once again SUPERB job! May I inquire as to which assembler one needs to use to compile the file: VirtualBox-4.3.6/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative.asm I tried as86 without success. Thanks!
nerd.brazil, Thank you! To compile VBoxBiosAlternative.asm you need to use yasm assembler. Note that the provided BIOS for 4.3.8 was recompiled from it's C sources that made possible to integrate MS SLP code without touching any BIOS function.
Thanks for the YASM tip... I suppose you had to use OpenWatcom compiler in order to compile directly from C sources, right? I had thought of another approach and wish to ask you opinion of it: (Using 4.3.6 for this approach) From the BIOS.BIN I would copy the entire _pci16_function region and move it towards the end where there is a bunch of 0x00. At the original _pci16_function address I would simply put a JMP command to the new address location. I would then be able to insert the SLP string without messing the _pci16_function. Basically I would manually do in assembly what you managed to do in C. It might be necessary to fix the addresses in the new region, e.g. a relative address to some fixed data. What's your thoughts on this?
nerd.brazil, You're right, to compile C sources of VirtualBox BIOS Open Watcom is needed. By the way, in the tar.gz source archive that can be downloaded from VirtualBox download page the makefile for Open Watcom is outdated and needs to be adjusted to achive byte-to-byte identical BIOS image that provided with VirtualBox distribution. Your solution is also can work. But as you said it needs to recalculate some address offsets. As you noticed in one of previous posts this job is needed to repeat each time VirtualBox releases and there is (IMHO) no easy way to make this using only decompiled ASM source. I found C sources more prefereable for this task because of at new VirtualBox release we need to: 1. Compare Makefile.kmk and Config.kmk from new and old releases to find what changed and adjust these changed in makefile for Open Watcom. 2. Compile BIOS using Open Watcom and found at BIOS map file what occupies the SLP memory region. 3. Edit needed C source inserting SLP dumb and recompile the BIOS again. As you see all ofsets are recalculated by compiler itself and there significantly lesser chance to make a mistake than calculating offsets manually. P.S. If you'll like to try compile C sources using Open Watcom this is the adjusted makefile: Code: # Compiler flags: # -q no banner # -wx max warnings # -0 generate 8086 code # -ms force small model (default) # -s remove runtime stack checks (required) # -os optimize for size # -zu assume that SS != DS (required) # -ecc default to __cdecl calling convention (bad idea) # !ifdef __UNIX__ Q=\" !else Q=" !endif CFLAGS = -q -3 -wx -zl -zu -s -oafs -ms -hc -d1+ CFLAGS32 = -q -wx -zu -s -oas -ms -nt=BIOS32 -nd=BIOS32 -hc -d1+ DEFS = -DVBOX -DVBOX_PC_BIOS -DVBOX_LANBOOT_SEG=0xE200 -DVBOX_VERSION_STRING=$(Q)4.3.8$(Q) & -DVBOX_WITH_SCSI -DVBOX_WITH_AHCI AFLAGS = -q -wx -d1 INCLS = -I$(Q)../include$(Q) .c.obj : .autodepend wcc -fo=.obj $(CFLAGS) $(DEFS) $(INCLS) $< .asm.obj : .autodepend wasm -fo=.obj $(AFLAGS) $(DEFS) $< OBJS = bios.obj print.obj ata.obj floppy.obj floppyt.obj eltorito.obj & boot.obj keyboard.obj disk.obj serial.obj system.obj invop.obj & timepci.obj ps2mouse.obj parallel.obj logo.obj scsi.obj & ahci.obj apm.obj pcibios.obj pciutil.obj vds.obj support.obj & pcibio32.obj apm_pm.obj pci32.obj orgs.obj vbxbios.rom : vbxbios.bin biossums $< $@ vbxbios.bin : $(OBJS) $(__MAKEFILES__) wlink name $@ system dos debug codeview all option quiet & option nofarcalls, map, verbose, statics, symfile & output raw offset=0xF0000 order & clname DATA segaddr=0xF000 segment _DATA & clname CODE & segment _TEXT segaddr=0xF000 offset=0x1600 & segment BIOS32 segaddr=0xF000 offset=0xDA00 & segment BIOSSEG segaddr=0xF000 offset=0xE000 & file { $(OBJS) } & library clibs.lib & disable 1014, 1023, 2120 logo.obj : logo.c .autodepend wcc -fo=.obj $(INCLS) $(CFLAGS) $(DEFS) -DVBOX_PC_BIOS $< pci32.obj : pci32.c .autodepend wcc386 -fo=.obj $(INCLS) $(DEFS) $(CFLAGS32) $< clean : .symbolic @rm -f *.obj *.err @rm -f vbxbios.bin vbxbios.rom vbxbios.map vbxbios.sym
Hi ailin! I am happy to inform that I had success with my method! For those reading this now, the attached BIOS retains all its original functionality while still being tattooed with Windows XP Mode SLP string. (VirtualBox 4.3.6) It was not difficult at all, I spent most time calculating by hand the relative addresses for the 5 CALLs because for some reason, "radare" hexeditor did not generate the correct disassembly for those CALLs. This method, while being in the realm of reverse engineering, is advantageous in that it does not require the source code, but it definitely speeded up the process... These were the hexeditor commands used on an extracted VirtualBox BIOS binary file (I used "radare" version 1 since version 2 had problems disassembling 16-bit code): Code: # radare -w pcbios.bin > e asm.arch=intel16 ;only needed if doing disassembly > s 0x9016 ;goto the beginning of _pci16_function at address 0x9016 > y 471 ;the function is 471 bytes long and is copied > wx e9 4c 04 ;replaced the function with a simple JMP to the new location 0x9465 > s 0x9465 ;goto the beginning of the empy space > yy ;paste the _pci16_function code > s 0x94dd ;goto 1st CALL > wx e8 3f fa ;replace with CALL 0x8f1f > s 0x9502 ;goto 2nd CALL > wx e8 1a fa ;replace with CALL 0x8f1f > s 0x952e ;goto 3rd CALL > wx e8 ca f9 ;replace with CALL 0x8efb > s 0x9610 ;goto 4th CALL > wx e8 b9 82 ;replace with CALL 0x18cc > s 0x9620 ;goto 5th CALL > wx e8 ea 82 ;replace with CALL 0x190d > q I then used "hexeditor" to paste the Windows XP Mode SLP exactly at 0x908a. Works perfectly! For those wishing to dig further into this method, here are a few info: + Use VBoxBiosAlternative-4.3.6.asm source file from VirtualBox source code. + With it you can find which function resides at the SLP region (0x908a-0x918e); in this case _pci16_function + You can find out how long this function is; in this case 471 bytes + You can find out where the empty space begins after all the code; in this case at 0x9465: 17,819 db 0x00 + After you move _pci16_function to the new address, check for addresses outside the function memory space and fix it; 5 CALLs found; all the JMPs and its derivatives were local jumps Attached is the edited pcbios.bin file for your own analysis. (Note: yes, I am a little late to the party since version 4.3.8 is already out... but I do this just for fun! I just got sidetracked with this little project... I never messed with BIOS ROM before hahaha!) edit: hmmm... in retrospect I should have edited the ASM file instead and compiled with YASM... but I guess using a hexeditor is waaay cooler!
I just checked the BIOS assembly source and nothing changed other than version number and a checksum digit. You may continue to use BIOS from 4.3.8 without any problems! === kali:tmp.r geek504$ diff VBoxBiosAlternative-4.3.8.asm VBoxBiosAlternative-4.3.10.asm 968c968 < db 'VirtualBox 4.3.8', 000h, 000h --- > db 'VirtualBox 4.3.10', 000h 16028c16028 < db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 04fh --- > db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 026h === cpu_reset: ; 0xffff0 LB 0x10 jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 026h === cpu_reset: ;; This is where the CPU starts executing after a reset jmp far ptr post ;; BIOS build date db BIOS_BUILD_DATE db 0 ; padding ;; System model ID db SYS_MODEL_ID ;; Checksum byte db 0FFh === BIOS_BUILD_DATEequ'06/23/99' SYS_MODEL_IDequ0FCh; PC/AT
Ok... I'm addicted to this BIOS hacking thing... I searched a while but didn't find anything related to this: 1) I have Lenovo Windows 8 Recovery Disc - can it be used somehow to install in VirtualBox? i.e. bypass hardware check 2) To decompress Phoenix BIOS, I am trying to find the ancient BEDEMO.ZIP from Phoenix... anyone has it? Thanks!