Now that we are using romcc, and all functions are inline, it is getting
increasingly painful to deal with linuxbios images smaller than 64k. This
problem happens as we need a 16-bit jump to the start of the linuxbios
code, which limits us to jumping to 0xffff0000. But if linuxbios is bigger
than that, we need to be able to jmp to 0xfffe0000, which is not possible
with the current setup.
We can grow this if we do the following:
make reset a rel jump to 0xfffffff0 - (sizeof entry16). Then put entry 16
right before 0xfffffff0. Entry16 code turns on 32-bit mode and then jumps
to the real start of the linuxbios image -- which can now be anywhere in
the flash image. I could use this now, as could others.
here is sample code which I am trying. It now assembles and inspection of
the object reveals that it is certainly close to correct.
Here's where I wish I had a really good emulator for linux -- checking
this out would be a whole lot easier.
The test reset16 code:
.type reset_start, @function
xorl %eax, %eax
movl %eax, %cr3 /* Invalidate TLB*/
movw %cs, %ax
shlw $4, %ax
movw $gdtptr16_offset, %bx
subw %ax, %bx
data32 lgdt %cs:(%bx)
movl %cr0, %eax
andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
orl $0x60000001, %eax /* CD, NW, PE = 1 */
movl %eax, %cr0
/* Now that we are in protected mode jump to a 32 bit code
data32 ljmp $ROM_CODE_SEG, $__protected_start
/** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment
* at 0x18; these are Linux-compatible.
.word gdt_end - gdt -1 /* compute the table limit */
.long gdt /* we know the offset */
The net effect is this: 16-bit reset jmps to a very small startup code
right before 0xfffffff0 that enables full 32-bit mode. We can then jmp
anywhere we want -- to 0xfffe0000 for example -- which we can't do now.
This will alleviate the problem of linuxbios images growing to > 64K which
is a consequence of romcc right now. This will allow us to live with
really big linuxbios images until romcc makes tighter code.
Comments? Errors in the code?