Re: Hook INT18 for IBM servers?
Glenn Brown <[email protected]>
| Newsgroups | gmane.network.etherboot.user |
|---|---|
| Message-ID | <[email protected]> |
Jarrod, Here's what I remember about the IBM BIOS I was using (in an IBM xSeries 346 machine), but our NICs have been used in lots of other IBM servers. It's not PnP. It doesn't set AX:DX to point to a '$PnP' structure, and no such structure exists in RAM if you scan for one. The BIOS calls INT18 to attempt to boot. There is no user interface to enable/disable individual PCI expansion ROMs. By default, PCI option ROMs are enabled, and will get a turn to boot the machine. The IBM BIOS is not BBS compliant. In particular, BBS says to use INT18 to return control to the BIOS, but IBM wants iret. If you use INT18 you will loop. Since the machine tries to boot from the NIC in the default boot configuration, IBM wanted our NIC to fail to boot quickly if the link is down. Conventional twisted-pair Ethernet handles this by not installing an INT18 handler at POST if the link is down. However, our NIC is 10Gb Ethernet, and some third party switches took >1s to bring the link up -- namely early HP ProCurve switches, but they've fixed that via a firmware upgrade -- so we modified Etherboot to defer the decision until INT18 was called, and early-exit if the link was down >1s after POST. This change is probably moot, since this was to address early 10G switches, but link detection in 10GE fundamentally only requires a few nanoseconds. Since iret is wedging your machine, I'd try the following: First, make iret be the first instruction executed in the INT18 handler. If this returns control to the BIOS, then you know that your BIOS expects iret and the problem is probably the stack. Undo this change once you've confirmed iret works as a trivial INT18 handler. Create a subroutine to print the 16-bit value in the AX register. This is not a great leap if you start with the Etherboot romprefix.S string printing function. Then use this function to print registers at INT18 entry and before iret. iret is probably failing because some register has not been properly restored. As I recall, it was very tricky to ensure that the stack pushes and pops were balanced by simply looking at the code. I think there was even a bug in Etherboot internals that failed to clean up memory allocation properly internally. Isolating this is practically impossible without a print function. Digging through my archive of patches, I found the attached relevant patch, which prints the amount of allocated base memory. If memory serves, and if this patch records the actual working code, this is how I found the leak in Etherboot. You can easily print other registers using the included print_ax function. For example, you can print %es with push %ax /* Save AX */ mov %es,%ax /* Move register-to-print into AX */ call print_ax /* print the value in AX */ pop %ax /* Restore AX */ Good luck! --Glenn ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Etherboot-discuss mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/etherboot-discuss
print_basemem.patch
(text/plain, 1.4 KB)
Index: src/arch/i386/prefix/romprefix.S =================================================================== RCS file: /repository/etherboot/src/arch/i386/prefix/romprefix.S,v retrieving revision 1.3 diff -a -u -a -u -r1.3 romprefix.S --- src/arch/i386/prefix/romprefix.S 23 Mar 2007 18:22:41 -0000 1.3 +++ src/arch/i386/prefix/romprefix.S 26 May 2007 02:32:27 -0000 @@ -251,7 +256,9 @@ pushw %ax /* Relocate to free base memory, switch stacks */ pushw $18 /* Preserve ROM length and CS & original AX and DS & original stack location & exit code & far ret addr */ + call print_basemem call prelocate + call print_basemem /* We are now running in RAM */ popw %ax /* discard stack length */ movw %cs, %ax @@ -435,3 +462,53 @@ 2: ret #endif + +print_al: + pushw %ax + pushw %bx + movw $0x0007, %bx + movb $0x0e, %ah + int $0x10 + popw %bx + popw %ax + ret + +print_ax: + /* Save registers. */ + pushw %ax + pushw %bx + pushw %cx + movw %ax,%bx + /* Print digits */ + mov $4,%cx +1: + mov %bh,%al + shr $4,%al + add $'a',%al + call print_al + shlw $4,%bx + loop 1b + /* Print newline */ + mov $'\r',%al + call print_al + mov $'\n',%al + call print_al + /* Restore registers and return */ + popw %cx + popw %bx + popw %ax + ret + +print_basemem: + pushw %ax + pushw %es + + movw $0x40, %ax + movw %ax, %es + movw %es:(0x13), %ax /* FBMS in kb to %ax */ + call print_ax + + popw %es + popw %ax + ret +