Summary:
There is a problem with the PCI and PNP headers in Etherboot ROMs which
causes them not to be recognized by certain modern PNP and "Legacy Free"
BIOSes. In my case the motherboard was a current offering by Intel,
model CA810EA. It is likely that this issue may affect other
motherboards as well, depending on their BIOS revision. This motherboard
has 4 PCI slots, onboard video and sound, and is a Micro-ATX form factor.
The behavior observed was that the ROM would be recognized by the Setup
screen of the BIOS as a potential BOOT device, but the ROM code would not
execute when selected as a boot device.
I have created a patch for the "loader.S" file in Etherboot which fixes
this problem. I have tested this patch by burning ROMs and Etherbooting
with an MX98715-based board on 4 different motherboards, some with legacy
slots, some without, and with various BIOSes. The patch is available at:
http://www.thinguin.org/
With the patch installed, it is possible to use the BIOS setup screen to
select, prioritize, or disable numerous boot (IPL) devices, and have them
checked in any order. In my case, I first check for a floppy, then for
"Etherboot ROM". It is also possible to install two Ethernet cards and
select which one to Etherboot from, if they are both capable.
Please note that the bug also exists in Netboot version 0.9.0e, and
should probably be fixed there as well.
Regards,
Marty
P.S. For those who would like to know how I figured this out, below is a
description of the debugging process. I mainly do this for the curious
and with the hope that others who have to debug such things can benefit
from time I spent gathering information and analyzing the problem.
The Tale:
Like so many interesting adventures, it started off innocently enough...
In preparation for LinuxWorld Expo in New York, I purchased an Intel
CA810EA, which is a modern Micro-ATX form factor motherboard. I liked it
because it had integrated AGP video, sound, and used PC100 RAM. It would
display well because the only PCI device would be an Ethernet card. it
also will fit in my suitcase along with a flat screen, so transportation
would be easier.
I built a machine with the CA810EA motherboard, using a Celeron 566Mhz
CPU with a large heat-sink so no CPU fan is needed. The power supply for
the case is virtually silent, because as we all know "Thin clients should
be seen and not heard".
I Etherbooted various PCI cards via floppy, and all looked very good. I
was just about to attach plexiglass sides to the case so people at the
show could see there was nothing inside except a NIC card with an
Etherboot ROM on it.
I then burned a ROM for an MX98715-based tulip clone card, and tried to
Etherboot with it. It didn't work. It was recognized by the BIOS setup
screen, but failed to execute. I tried various BIOS settings, but to no
avail.
To determine if this was a problem with the boot ROM, I tested the
motherboard with an Intel PRO/100+ card and a 3Com 3C905C-TX-M card, both
of which have integrated flash memory containing PXE network booting
code. Both commercial cards were recognized by the BIOS, and attempted to
network boot.
Because the MX98715 board's ROM was at least selectable by the BIOS, I
suspected that it was at seeing a ROM on the card, but for some reason
didn't think it was correct for network booting.
Time to take a look inside
Using the contrib/3c90xutil/cromutil utility program from the Etherboot
package I dumped the Flash memory contents of the working 3Com
3C905C-TX-M board to a file. Using the techniques described in the
Etherboot contrib/3c90xutil/eepro100notes file, I dumped the flash memory
contents of the pro/100+ adapter as well. I already had the
mx98715.lzrom code for Etherboot, of course.
Here is a hex dump of the first part of each of those ROM images:
-:---F1 mx987x5.lzrom (Hexl)--L3--Top---------------------------
00000000: 55aa 20eb 4f31 e98c 0045 7468 6572 626f U. .O1...Etherbo
00000010: 6f74 0000 0000 0000 1c00 3400 5043 4952 ot........4.PCIR
00000020: d910 3105 0000 1800 0000 0002 2000 0100 ..1......... ...
00000030: 0080 0000 2450 6e50 0102 0000 0061 0000 ....$PnP.....a..
00000040: 0000 0000 0000 0000 0214 0000 0000 5400 ..............T.
00000050: 0000 0000 501e 31c0 8ed8 a104 033d 4ce4 ....P.1......=L.
-:---F1 3c905c.img (Hexl)--L7--Top-----------------------------
00000000: 55aa 08e9 af07 554c 4452 0000 0003 0000 U.....ULDR......
00000010: 0000 d006 4005 7000 5800 3800 6d00 0004 ....@.p.X.8.m...
00000020: cc00 0010 0427 10d4 3005 0000 0000 0000 .....'..0.......
00000030: 0000 0000 0000 0000 2450 6e50 0102 0000 ........$PnP....
00000040: 00e2 0000 0000 c300 c800 0200 0014 0000 ................
00000050: 0000 4503 0000 0000 5043 4952 b710 0092 ..E.....PCIR....
00000060: 0000 1800 0002 0000 6d00 0000 0080 0000 ........m.......
-:---F1 pro100+.img (Hexl)--L7--Top-----------------------------
00000000: 55aa 14e8 3f23 cbc4 d502 0000 0000 0000 U...?#..........
00000010: 0000 0000 0000 2000 4000 6000 5503 2001 ...... .@.`.U. .
00000020: 554e 4449 1605 0000 0102 130e 0008 604b UNDI..........`K
00000030: 9020 5043 4952 2e8b c02e 8bc0 2e8b c090 . PCIR..........
00000040: 5043 4952 8680 2912 0000 1800 0002 0000 PCIR..).........
00000050: 1400 0102 0080 0000 2e8b c02e 8bc0 8bc0 ................
00000060: 2450 6e50 0102 0000 0020 0000 0000 9b00 $PnP..... ......
00000070: bc00 0200 00e4 0000 0000 610d 0000 0000 ..........a.....
Decoding the ROMs
Using the specifications for Option ROM Headers described in the document:
http://www.phoenix.com/products/specs-bbs101.pdf
I decoded three headers from each ROM, and created a table to compare the
Etherboot ROM to the 3Com and Intel ROMs. I then studied the
specifications to see whether the ROM contents made sense for each field.
Here is a table showing the decoded headers:
A.2 PnP Option ROM Header
Etherboot 3Com Intel
Offset Size before fix 3C905C PRO/100+ Description
00h B 55h 55h 55h Signature byte 1.
01h B AAh AAh AAh Signature byte 2.
02h B 20h 08h 14h Option ROM len 512byte blks.
03h B*4 eb4f31e9h e9af0755h e83f23cbh Initialization entry point.
07h B*17 Reserved.
18h W 1c00h 5800h 4000h Offset to PCI data struct.
1Ah W 3400h 3800h 6000h Offset to expansion hdr.
A.3 PnP Expansion Header
Etherboot 3Com Intel
Offset Size before fix 3C905C PRO/100+ Description
00h B '$' '$' '$' Signature byte 1.
01h B 'P' 'P' 'P' Signature byte 2.
02h B 'n' 'n' 'n' Signature byte 3.
03h B 'P' 'P' 'P' Signature byte 4.
04h B 01h 01h 01h Structure revision.
05h B 02h 02h 02h Length (16 byte increments).
06h W 0000h 0000h 0000h Offset of next hdr
08h B 00h 00h 00h Reserved.
09h B 61h e2h 20h Checksum.
0Ah DW 00000000h 00000000h 00000000h Device identifier.
0Eh W 0000h c300h 9b00h Ptr to mfgr str. (opt)
10h W 0000h c800h bc00h Ptr to prod name str (Opt)
12h B*3 000002h 020000h 020000h Device type code.
15h B 14h 14h e4h Device indicators.
16h W 0000h 0000h 0000h Boot Connection Vector (BCV)
18h W 0000h 0000h 0000h Disconnect Vector (DV)
1Ah W 5400h 4503h 610dh Bootstrap Entry Vector (BEV)
1Ch W 0000h 0000h 0000h Reserved.
1Eh W 0000h 0000h 0000h Static res info vector
A.4 PCI Data Structure
Etherboot 3Com Intel
Offset Size before fix 3C905C PRO/100+ Description
00h B 'P' 'P' 'P' Signature byte 1.
01h B 'C' 'C' 'C' Signature byte 2.
02h B 'I' 'I' 'I' Signature byte 3.
03h B 'R' 'R' 'R' Signature byte 4.
04h W d910h b710h 8680h Vendor Identification.
06h W 3105h 0092h 2912h Device Identification.
08h W 0000h 0000h 0000h Ptr to Vital Product Data.
0Ah W 1800h 1800h 1800h PCI Data Structure Length.
0Ch B 00h 00h 00h PCI Data Structure Revision.
0Dh B*3 000002h 020000h 020000h Class Code.
10h W 2000h 6d00h 1400h Image Length.
12h W 0100h 0000h 0102h Revision Level of Code/Data.
14h B 00h 00h 00h Code Type.
15h B 80h 80h 80h Indicator.
16h W 0000h 0000h 0000h Reserved.
Eureka!
Note specifically the values at offet 12h of the PnP Expansion Header and
offset 0Dh of the PCI Data Structure. It appears that they are in
reverse order in the Etherboot ROM. Referring the the Device ID
specification available at:
http://www.microsoft.com/hwdev/download/respec/devids.txt
we note that the 3 bytes of the Device code should be:
Base Type = 2: Network Interface Controller
Sub-Type = 0: Ethernet
Interface Type = 0: General Ethernet
which they are, in the Intel and 3Com ROM images. It seems they are
simply reversed in the Etherboot ROM.
referring to the relevant portion of src/loader.S in Etherboot, we see:
PCI:
STRDECL('PCIR') ; signature
dw 0x8086 ; vendor ID, filled in by makerom
dw 0x1229 ; device ID, filled in by makerom
dw 0x0000 ; pointer to vital product data
dw 0x0018 ; PCI data structure length
db 0 ; PCI data structure revision
db 0 ; Class code byte 1
db 0 ; Class code byte 2
db 0x02 ; Class code byte 3 (from
hexdumping
; Intel bootrom image)
dw 0x0000 ; Image length same as offset 02h
dw 0x0001 ; revision level of code /data
db 0 ; code type
db 0x80 ; indicator (from hexdumping
; Intel bootrom image)
dw 0x0000 ; reserved
and
PnP:
STRDECL('$PnP') ; signature
db 0x01 ; structure revision
db 0x02 ; length (in 16 byte increments)
dw 0x0000 ; offset of next header
db 0 ; Reserved
db 0 ; checksum filled by makerom
dd 0x00000000 ; Device identifier
dw 0x0000 ; pointer to manufacturer str
dw 0x0000 ; pointer to product name
db 0 ; device type code byte 1
db 0 ; device type code byte 2
db 2 ; device type code byte 3 (from
; hexdumping Intel bootrom image)
db 0x14 ; device indictors (from
; hexdumping Intel bootrom image)
dw 0x0000 ; boot connection vector
dw 0x0000 ; disconnect vector
dw start19h ; bootstrap entry vector
dw 0x0000 ; reserved
dw 0x0000 ; static resource information
vector
note the order of the "class code" and "device type code" bytes. It is
reversed from the order specified in the PnP specification.
>From the file netboot-0.9.0e/bootrom/loader/rom.S file we see:
! Define the PCI data structure to make the netboot bootrom compatible
! with the PCI local bus specification 2.1. This header is actually only
! needed when the bootrom is physically located on the PCI network card.
! Note that the order of the class codes has to be reversed compared to
! what the spec says.
pcihdr: .ascii "PCIR" ! signature for PCI data structure
.word 0 ! vendor ID (filled in later)
.word 0 ! device ID (filled in later)
.word 0 ! ptr to vital product data
(unused)
.word $0018 ! length of PCI data structure
.byte $00 ! structure revision 0.0
.byte PCI_IFTYPE ! device programming interface
.byte PCI_SUBTYPE ! device subtype code
.byte PCI_BASETYPE ! base device type code
.word 0 ! rom image length (filled in
later)
.word PCI_REVISION ! version number of code/data
.byte 0 ! code type
.byte PCI_DEVIND ! device indicator
.word 0 ! reserved
! Define the expansion header to make the netboot bootrom Plug and Play
! compatible according to the Plug and Play BIOS Specification 1.0A. This
! will allow the system BIOS to select wether to boot from the network or
! not, and we dont have to redirect interrupt 18h or 19h by ourselves.
! Note that the order of the class codes has to be reversed compared to
! what the spec says.
pnphdr: .ascii "$PnP" ! signature for PnP expansion
header
.byte $01 ! structure revision 0.1
.byte 2 ! length of header in
16-byte-blocks
.word 0 ! pointer to next header (0 =
none)
.byte 0 ! reserved
.byte 0 ! checksum (filled in later)
.word PNP_VENDID ! compressed manufacturer code
.word PNP_DEVID ! product number and revision,
device ID
.word 0 ! ptr to manufacturer string
(unused)
.word prdnam ! ptr to product name
.byte PNP_IFTYPE ! device programming interface
.byte PNP_SUBTYPE ! device subtype code
.byte PNP_BASETYPE ! base device type code
.byte PNP_DEVIND ! device indicators
.word 0 ! boot connection vector (unused)
.word 0 ! disconnect vector (unused)
.word dorom ! bootstrap entry vector
.word 0 ! reserved
.word 0 ! static resource info vector
(unused)
Note that the author specifically reversed the order of the PCI and PNP
class codes. I suspect there must have been a BIOS implementation bug
that caused cards following the specification not to work at the time,
because the 1.0A specification states:
"Device Type Code - This field contains general device type
information that will assist the System BIOS in prioritizing the boot
devices. The Device Type code is broken down into three byte fields.
The byte fields consist of a Base-Type code that indicates the general
device type. The second byte is the device Sub-Type and its definition
is dependent upon the Base-Type code. The third byte defines the
specific device programming interface, IF.-Type, based on the Base-Type
and Sub-Type."
We have liftoff
WIth this information and analysis I reversed the codes in the Etherboot
ROM code, burned a ROM, and it was properly recognized by the BIOS.
I also added preliminary manufacturer and product strings to the header
to allow the string "Etherboot ROM" to appear in the BIOS setup menu for
boot device. Without this, it says "Option ROM" which is less
descriptive. With a little more work, we could embed the actual ROM type
as well at compile time so it would say "Etherboot 4.6.12 MX987x5.lzrom"
or something more descriptive. According to the spec, the first 32 bytes
are significant, though no length limit for the string is specified.
I burned a second ROM (an LC82C115.lzrom) to test a second card type, and
it also functioned.
The third ROM was an RTL8139.lzrom. This one was not recognized
initially by the BIOS. I booted to DOS and ran a utility to enable the
ROM socket and specify the size of the ROM. Still no joy.
I noted that in this 3rd case, the ROM was not even being seen by the
BIOS setup screen. This suggested that there might be something
physically wrong with the ROM. Though it was the same speed as the other
ROMs it appears that the RTL8139 card was not inserting enough wait
states to mediate between the bus speed (66MHZ) and the ROM speed. I
burned a faster ROM (150ns vs. 250ns) and the ROM was recognized and
booted properly.
I then took the three cards and Etherbooted them on four different CPUs
with various BIOS and legacy configurations. They seemed to function
properly.
Cut to the present
So, that's where we are now. I can now continue to prepare for
LinuxWorld Expo, and show a modern motherboard with various modern PCI
cards Etherbooting from a Linux box and running X.
Hopefully my experience will help others who are debugging such problems.
Network booting is a very useful technology, and I am pleased to be able
to contribute to making it more widespread and accessible.
Marty
---
Try: http://rom-o-matic.net/ to make Etherboot images instantly.
Name: Martin D. Connor
US Mail: Entity Cyber, Inc.; P.O. Box 391827; Cambridge, MA 02139; USA
Voice: (617) 491-6935, Fax: (617) 491-7046
Email: mdc@thinguin.org
Web: http://www.thinguin.org/
===========================================================================
This Mail was sent to netboot mailing list by:
Marty Connor <mdc@thinguin.org>
To get help about this list, send a mail with 'help' as the only string in
it's body to majordomo@baghira.han.de. If you have problems with this list,
send a mail to netboot-owner@baghira.han.de.
For requests or suggestions regarding this mailing list archive please write to netboot@gkminix.han.de.