Hi,
On 6/12/07, Stefan Reinauer stepan@coresystems.de wrote:
- Brendan Trotter btrotter@gmail.com [070612 12:43]:
check LinuxBIOSv2/util/lbtdump
I've found "src/include/boot/linuxbios_tables.h" and have also looked at the source for LinuxBIOSv2/util/lbtdump.
However, I fail to see how any source code can be considered a viable alternative to documentation for something that is (hopefully) a non-proprietory common standard. Reverse engineering (including relying on assumptions derived from the source code of any specific implementation) is what people do when they have no documentation and are willing to stumble around in the dark hoping to implement something that works until the wind changes.
Yes, no doubt. You are perfectly right, and we are looking forward to your patches to fix this problem. Of course you do not have to reverse engineer, but just read the code, as we are non-proprietary. And of course we are always here to be asked.
Hehe - by the time you've finished answering all my questions you'd wish you'd written the documentation beforehand... ;-)
Is "uint32_t" always little-endian or is it architecture specific (reverse engineering ruled out "always big-endian"), and would the "lb_header.signature" field always have an ASCII 'L' at the lowest address (or is that architecture specific too)?
The source file "util/lbtdump/lbtdump.c" does this:
if (head->header_bytes != sizeof(*head)) { fprintf(stderr, "Header bytes of %d are incorrect\n", head->header_bytes); continue; }
From this can I assume that the size of the LinuxBIOS Table header
will always be 24 bytes, and the LinuxBIOS Table header will never be extended in the future (or is this just a bug that makes "lbtdump" unable to handle forward/backward compatability)?
The file "src/include/boot/linuxbios_tables.h" defines 3 types of memory ranges:
#define LB_MEM_RAM 1 /* Memory anyone can use */ #define LB_MEM_RESERVED 2 /* Don't use this memory region */ #define LB_MEM_TABLE 16 /* Ram configuration tables are kept in */
The file "util/lbtdump/lbtdump.c" doesn't agree:
switch(rec->map[i].type) { case 1: mem_type = "ram"; break; case 3: mem_type = "acpi"; break; case 4: mem_type = "nvs"; break; default: case 2: mem_type = "reserved"; break; }
Can I assume that the defines in "linuxbios_tables.h" are out-of-date, and that the memory type field is the same as specified by version 2 of the ACPI specification (but perhaps not version 3, as that defines a new "5 = faulty RAM" type)? If "linuxbios_tables.h" is out-of-date, is "16 = RAM configuration tables are stored in" still possible on older versions of LinuxBIOS (and how would I detect which version of LinuxBIOS is present, considering there's no version number in the LinuxBIOS Table header)?
What is the LB_TAG_HWRPB structure. Is it something to do with a "Hardware Restart Parameter Block", and what does it contain? For e.g. would a value of zero indicate that the computer was shutdown correctly before boot, and a non-zero value indicate that the computer crashed or had hardware problems?
Would I also be correct to assume that a payload doesn't need to care about any of the "cmos_entries" and "cmos_enums", unless a BIOS setup/configuration utility is being built into the payload? Alternatively, could/would a payload search for strings to find CMOS values (e.g. search for the cmos_entry with the name string "power_on_after_fail" to see if additional hardware testing can be skipped, search for "baud_rate" to determine the serial port configuration, etc)?
It is of course not unique. It is the index of the vendor name within the strings array of struct lb_mainboard. Since we're not trying to close things down, we don't have to work with magic numbers. So nothing needs to stay unique.
Of course - it's similar to the way SMI/DMI does strings, yet are the strings themselves guaranteed to be unique, or is it possible for one manufacturer to use an identifying string in the future that another (possibly out of business) manufacturer had used in the past?
Motherboard manufacturer identification is one of the things that (IMHO) should be unique. The motherboard part number string should also be unique for that manufacturer ID. Otherwise it'd be difficult for payloads/utilities/OSs to use these IDs to avoid any hardware problems in specific motherboards.
I assume there may also be ACPI, MP specification, PIRQ routing and/or (possibly) SMI/DMI tables, and I'm guessing that (if present) these tables can be searched for using the same methods as described in their corresponding specifications.
They're not used by payloads (except the Linux kernel)
Surely LinuxBIOS isn't intended as a "Linux only" BIOS though....
Of course not. ACPI is not really useful for payloads though, unless the payload wants to carry a full blown ACPI interpreter. Which rules out basically anything but an OS.
I can think of a variety of uses, ranging from utilities that do nothing more than display hardware information, to diagnostics, to benchmarking, to hyper-visors, to full OSs...
- are AP CPUs started (or waiting for a SIPI sequence)?
yes, hardware is completely up when linuxbios is done.
I tried it on a dual CPU Bochs emulation (second CPU was left in "wait for SIPI" state) - I'm guessing I need to enable multi-CPU support via. some compile time option for the "emulation/qemu-i386" target?
Yes, the emulation/qemu-i386 is per default not supporting SMP.
I'm becoming skeptical here. I can't find anything in LinuxBIOS source code that starts AP CPUs, but in "src/arch/i386/smp/mpspec.c" I did find:
/* If we assume a symmetric processor configuration we can * get all of the information we need to write the processor * entry from the bootstrap processor. * Plus I don't think linux really even cares. * Having the proper apicid's in the table so the non-bootstrap * processors can be woken up should be enough. */
It might be possible that no AP CPUs are ever started, and are instead left in a "wait for SIPI" default state, assumed to be identical to the BSP, and even assumed to be working (no BIST checks).
AFAIK the normal approach is to send a broadcast INIT-SIPI sequence and wait to see which AP CPUs start (if any), and then either record details somewhere or have each AP CPU add itself to the MP specification and ACPI tables, then setup their MTTRs, thermal monitoring, HT links, SMBASE, etc before sending the APs back to the "wait for SIPI" state - i.e. in theory it should be mostly "configuration-less".
In any case, I'm guessing I need to get LinuxBIOS to generate MP specification and ACPI tables to suit the number of CPUs being emulated by Bochs/Qemu. Is this as simple as adding something like "option CPUs = ?" to the "targets/emulation/qemu-i386/Config.lb" file? I'm guessing it's more involved than this, as I couldn't find an example in the "Config.lb" of other targets.
Either: a) PCI buses and bridges aren't guaranteed to be enumerated, or b) PCI buses and bridges are guaranteed to be enumerated but PCI devices aren't guaranteed to be assigned resources, or c) PCI buses and bridges are guaranteed to be enumerated and PCI devices are guaranteed to have resources assigned (including ROMs) d) PCI buses and bridges are guaranteed to be enumerated and PCI devices are guaranteed to have resources assigned (except ROMs)
"They have their resources." would mean either c) or d), where each device may or may not be in a power saving state (if supported by the device), and may or may not be still configured to use MSI (if supported by the device)....
yes, either c or d. You choose.
You mean all LinuxBIOS developers are willing to make sure all PCI device ROMs either have physical addresses assigned or don't have physical addresses assigned based on my advice? Perhaps I've misunderstood... :-)
Not at the moment. But in General this is easy. If no VGA class PCI device is there, the machine is 99.99% headless.
And if a VGA class PCI device is present, you've got no idea if no monitor is attached...
Obviously not. and if the device does not do EDD you have no reliable way of finding out either.
There's a simple and easy way to find out if a monitor is attached or not, and it doesn't involve messing about with EDD - simply give the end-user the option of setting (or not setting) a value in the CMOS.
My (limited) reverse engineering has already shown that there's CMOS entries for a serial port (possibly intended for setting up a serial cable to communicate with a terminal emulator?).
- can anything be assumed about AGP and the first video card (if the
computer isn't headless)?
What would you like to assume?
Video card set to default "80 * 25" text mode accessible at 0xB8000; or some video mode set with display memory directly accessible at some physical address (where video mode details and physical address included in LinuxBIOS Table); or AGP aperture configured, AGP transfer speed set, MTRRs set to "write combining" and some video mode set with display memory directly accessible at some physical address; or anything else, as long as a payload writer knows how much or how little they can assume about it (and hopefully doesn't need to implement a wide range of video drivers just to do a "Hello World" that works on all video cards)... ;)
Ok, the video hardware is in the state that the VGA Option ROM sets it to. Since that is closed source, we can not guarantee anything, obviously. A rule of thumb tells you that 80x25 at B8000 is a reasonable assumption. The AGP setup is chipset specific, so it might vary from chipset to chipset.
Cool :-)
Next question would be how to get that to work under Qemu and/or Bochs. I realise this may not be easy (I've had problems with Bochs before, as the VGA ROM seems to behave like an ISA card ROM and doesn't behave like a PCI card ROM - i.e. the ROM ignores settings in PCI configuration space)...
Thanks,
Brendan