VOGONS


First post, by Sebastian-vgns

User metadata
Rank Newbie
Rank
Newbie

Many older notebooks do not allow you to install an Option ROM for XTIDE, for example, which makes it difficult to use CF cards or larger hard drives. I considered simply replacing the IDE code in the BIOS, but during my analysis, I noticed that many BIOS ROMs still have enough free space to integrate an Option ROM.

I succeeded in doing this for one BIOS, and so that it could be used efficiently for all kinds of things, I built it into a Python script. This allows you to integrate any Option ROM into a BIOS ROM image, provided there is enough space. The script supports numerous BIOS manufacturers and is suitable for BIOS ROMs from the 286 and 386 era. Perhaps others as well. The ROM must not be compressed.

Maybe it will help you get CF cards working in old notebooks or do other great things.
I welcome feedback, optimizations, and additional BIOS images that the script does not yet recognize.

You find the script and the description how it works here:
https://github.com/Sebastian-gthb/insert-OptROM-into-BIOS

Have fun with integrating option ROMs!

Best regards,
Sebastian

Reply 1 of 7, by Jonas-fr

User metadata
Rank Member
Rank
Member

This is really relevant to my interest, cheers!

Reply 2 of 7, by Sebastian-vgns

User metadata
Rank Newbie
Rank
Newbie

Thanks Jonas-fr! Let me know if it works and also if it not. So I can improve the improve the script.

I added a new script that visualize the BIOS ROM image with the allocated and free space (VisualizeFreeSpace.py). It's a little bit interesting to understand the BIOS ROM. I think the BIOS ROMs are modular and and were assembled with tools. So we have some free spaces between the modules that can we use for other code.

This is a visualization of a Bondwell B310 BIOS ROM image:
file.php?mode=view&id=233843

Reply 3 of 7, by douglar

User metadata
Rank l33t
Rank
l33t

This is very exciting. What is required to use those free blocks?

Reply 4 of 7, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

Tools to optimize/compactify the code sections, so that free blocks are more contiguous would be neat too.

Reply 5 of 7, by Sebastian-vgns

User metadata
Rank Newbie
Rank
Newbie
douglar wrote on Yesterday, 19:14:

This is very exciting. What is required to use those free blocks?

Hi douglar,

What you mean with "What is required to use those free blocks?"

At first you need an image of the BIOS ROM from your old vintage x86 computer. With some luck in this ROM is enough empty space to put a option ROM like XTIDE or a network boot ROM into the BIOS ROM chip. The script of my GitHub repo analyse the image and do the job to merge the two ROMs together. If the script was successful, you need a empty EPROM or EEPROM and a device to write the new image into this ROM chip (called eprom programmer). The EPROM must be compatible to the original ROM chip from the vintage computer and must have the same size. If it's done remove the original BIOS ROM and put the new ROM chip into your computer and try to boot like the normal BIOS with the new implemented Option ROM.

An Option ROM is... https://en.wikipedia.org/wiki/Option_ROM

I hope this was helpful, or let me know if not.

best regards
Sebastian

Reply 6 of 7, by Sebastian-vgns

User metadata
Rank Newbie
Rank
Newbie
wierd_w wrote on Yesterday, 21:20:

Tools to optimize/compactify the code sections, so that free blocks are more contiguous would be neat too.

Hi wierd_w,

yes this is a nice idea! But its maybe a hard way. In the BIOS code there are many or thousands of jumps and calls to different other code addresses (see picture example). If we "defragment" the ROM we must find all of this jumps and recalculating to the new jump destinations. The most times we have relative (near) jumps they are maybe ok but if they located to the same code block. If they are used between tow code block that we move, we must recalculating. Each absolute (far) jumps and calls we must recalculating. So that can be possible but it's a hard way.

At next we have maybe a interrupt vector table hard coded in the ROM. This table describe on which memory address is the subroutine of a software or hardware interrupt. It's hard to find this table between the program code and we must maybe recalculating the memory addresses of this table.

But sometimes the BIOS manufactures do confusing things, maybe to be harder to disassembling the code: They do a jump with the return command...
A normal call to a code address save the next code address into the stack, jump to the destination of the call, execute this code and at the end of this routine is a return command. This return commend read the saved code address from the stack and jump to this address and execute this code. The return is also a jump command that reads the destination from the stack. Some manufactures use:

mov ax,0x1234
mov bx,0xABCD
<-- you can have some code there
push ax
push bx
<-- you can have some code here
ret

insead of:

jmp 0x1234:0xABCD

And this extreme hard to analyse this with a simple script.

Long story short... it's a cool idea but... extreme hard to do!

example picture of disassembled code:
file.php?mode=view&id=233969

Reply 7 of 7, by wierd_w

User metadata
Rank Oldbie
Rank
Oldbie

It would not necessarily need to be 'guaranteed maximum compaction' like that.

Simply looking for dead space between service routines, (with sanity checks for routines that expect certain things about where in the segment they are, for instance, 'implicitly expect to be aligned a certain way', for example, some comparison operations are more efficient/only make sense with the opeands being read from an even-numbered byte, or, where the code implicitly thinks it will always be at the top of a segment, and makes assumptions based on that, etc) without trying to get every last byte wasted back that is contained inside a routine, is more reasonable.

(You have a routine that is 20kb in size, and then there is dead space after. There is another routine that is 12kb in size that does not make assumptions like above, that can be moved into the space, creating 32k of well packed entries. We dont care about space or padding inside the routine itself, just the way its packed)

granularity at just the routine itself, more or less, so that if for some reason, there's a code segment for a routine that will fit inside a patch of space, and this relocation does not require heavy patching of the return and jump addresses inside the routine itself, then consider the code 'relocatable', and offer to relocate it.

This wont give fully compactified code segments, but might permit a more complicated injection to be done afterward.