[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Multiboot2 Suggestions
Re: Multiboot2 Suggestions
Sun, 4 Apr 2010 17:27:05 +0930
2010/4/3 Vladimir 'φ-coder/phcoder' Serbinenko <address@hidden>:
> Brendan Trotter wrote:
>> 1) If GRUB was using a serial port as a console device (e.g. on a
>> headless system) it'd be nice if the OS could continue using the same
>> serial port with the same configuration instead of resetting the
>> serial port, etc. A new tag (for 80x86, "8250/6550 compatible" serial
>> ports) would include base I/O port, the serial line configuration
>> (e.g. 8 data bits, no stop bit, no parity), the baud rate (e.g. 9600),
> The kernel can read data bits, stop bits, parity and divisor from
> registers itself. I think it's more useful to supply a base frequency
> since there are a lot of "almost compatible" cards which differ only in
> base frequency.
>> the IRQ number (if known/used by the boot loader) and the protocol
>> being used (ASCII, VT100, etc).
> I think it's more useful to supply directly usable strings termcap
> strings rather than an abstract ID
Here's an example termcap string:
:al=3*\E^R:am:bl=^G:cd=16*\E^C:ce=16\E^U:cl=2*^L:cm=\Ea%+ %+ :\
Making sense out of arbitrary termcap strings isn't easy - it would
add a large amount of mess to early OS initialisation code (which
typically doesn't even have C library functions to rely on). A single
integer saying "which protocol" is much easier to parse and use,
especially as only a few standard protocols (e.g. VT100) would need to
>> If the boot loader doesn't know which
>> IRQ the serial port uses (e.g. it uses polling) then it sets the IRQ
>> number to 0xFFFFFFFF.
>> Where the serial port has a different interface
>> (e.g. if the serial port uses MMIO or if it's not "8250/6550
>> compatible") a different tag with different fields are used to
>> describe it.
> I think it's more useful to have an I/O selector since yeeloong serial
> interface is basically the same, just attached differently
An I/O selector (for "8250/6550 compatible") makes sense, and
different tags for "not 8250/6550 compatible" serial ports.
> I think we need following fields:
> 1) I/O space selector (e.g. 0 = 32-bit MMIO, 1 = 64-bit MMIO, 2 = i386 I/O)
For 32-bit MMIO you could use 64-bit MMIO with the high bits of the
"address in I/O space" set to zero.
> 2) IRQ type selector (0 = None, 1 = standard platform interrupt)
> 3) 16-bit padding
> 4) address in I/O space (up to 64-bits)
> 5) Base frequency in Hz (32-bit)
> 6) IRQ (32-bit or even 64-bit since it's not excluded some platforms would
> use 64-bit IRQ ids, though I'm not aware of such).
Looks good to me.
> It would need network tag first
Just an example of a different tag for a different type of console device.
>> 2) The "OS image format" information should be expanded, so that the
>> OS can tell the boot loader if it supports "8250/6550 compatible"
>> serial ports (and which protocols), and any other console devices (for
>> the same reason the "OS image format" already has flags, etc for
> Console flags tag is for this
Yes - the console flags tag needs to be expanded...
>> 3) There should be an (optional?) "critical error notification method"
>> tag that tells the OS which method/s it can/should use to tell the
>> user it encountered a problem before it was able to setup it's console
>> output. For example, can/should the OS return to the boot loader, or
>> use the "PC speaker" to beep, or make a PS/2 keyboard's LEDs flash, or
>> something else.
> Processing such a selector may prove as difficult as setting up a
> console based on console tags. So I doubt its usefullness
I currently use "PC speaker" as my "critical error notification
method" - it's about 15 instructions that use I/O ports only and
doesn't require memory allocations or anything else. I doubt setting
keyboard LEDs (for a PS/2 keyboard) would be much larger or rely on
anything more than I/O ports.
In comparison, my video setup code is around 64 KiB of code that
starts with trying to get EDID information from the monitor, filtering
a list of video modes (from VGA and/or VBE), allocating several MiB of
RAM for video buffers and font data, scaling font data, etc. If
there's a problem setting up the memory management it's all useless
and I fall back to the "critical error notification method" so the
user knows the OS failed to initialise something (e.g. couldn't
allocate several MiB of RAM).
Alternatively, (for my OS) for headless systems; I use RTS/CTS and the
VT100 "identify" command to detect if anything is listening on the
serial port (and if it's a terminal or something else). When nothing
is listening on the other end the OS can't talk so it uses the PC
speaker as a fallback (but continues monitoring the serial port).
Basically if something goes wrong at any stage, the OS beeps, and the
user can plug a terminal in afterwards to find out what went wrong
(rather than having no idea what caused the problem, then connecting a
terminal and rebooting to see if it happens again while they are
>> 5) The boot loader should always provide a "memory map". If the boot
>> loader is unable to get a memory map from the firmware then the boot
>> loader constructs a fake memory map from any/all information it can
>> find, including known areas that aren't RAM. For e.g. on "80x86 BIOS"
>> if "int 0x15, eax=0xE820" isn't supported, then other BIOS functions
>> are used to find usable RAM and the boot loader creates an entry that
>> marks the area from 0x000A0000 to 0x000FFFFF as "system" or "unknown".
> Where bootloader gets memory map from isn't part of specification and I
> see no reason to change that
The examples are examples (intended to illustrate why/how the boot
loader would create a memory map when the firmware doesn't provide
one; rather than intended for inclusion in the spec).
>> 7) The memory map needs more "area types". Any RAM that is reported by
>> firmware as faulty should use "area type 5" so that the OS can know
>> that some RAM is faulty, and (for e.g.) could tell a system
>> administrator about it. Also, "area type 0xFFFFFFFF" should be used
>> for "unknown", as this allows the OS to determine the difference
>> between "boot loader doesn't know what the area is" and "boot loader
>> does know what the area is but the area type is defined in a newer
>> version of the multi-boot specification".
> What's the difference between type 2 and "type 5"
For a server environment, would your OS automatically send an email to
an administrator warning them that an area of memory is marked as
>> 8) Any RAM that is not immediately usable by the OS should not be
>> reported as "usable RAM" in the memory map. An example of this is the
>> "ACPI reclaimable" area (which is RAM that isn't usable until the OS
>> has finished using the ACPI tables). RAM used to store the multi-boot
>> information, RAM used to store the "kernel" and RAM used to store any
>> modules should be treated in the same way. I suggest using "area type
>> 0xFFFFFFFE = RAM used for multi-boot information" and "area type
>> 0xFFFFFFFD = RAM used for kernel/modules". This makes it much easier
>> to write a kernel's early initialisation code, because it can use RAM
>> without worrying about trashing data that is needed by the kernel/OS
> kernel should know itself what it asked bootloader to do. MBI now is a
> single chunk. Further than that there are only elf section tag and
> module tags which refer to external memory. I think it should be easily
> trackable now.
Unfortunately a lot of OSs are written by C programmers who do the
absolute minimum to setup paging in a small piece of startup code
written in assembly, before jumping to their "main()". This means they
allocate RAM for page tables, etc before they've parsed or checked
anything; usually by searching the memory map for the first "usable"
area and using the first pages of that area.
Unfortunately I'm often the person that needs to explain to them that
"usable" doesn't mean usable; and that their code only works by
accident (and their initialisation code could overwrite things needed
by the OS later if it's booted by a different multi-boot compliant
boot loader; including future versions of GRUB and not excluding
non-GRUB boot loaders); and that the only memory they can safely use
before determining what is usable and what isn't is the space in their
".bss", which usually happens to be linked to a virtual address (e.g.
above 0xC00000000) and not the address it's actually loaded at.The
other alternative is for the initialisation code to copy everything
from the "usable" areas into their ".bss" so that they can assume that
"usable" means usable (but there's no maximum size for the multi-boot
information and no way to know how big "big enough" is, and this won't
work if there's any extra modules).
Basically, regardless of how the OS handles the problem, the "small
piece of startup code written in assembly" ends up being an ugly mess.
If multi-boot guaranteed that "usable" actually did mean usable then
the problem goes away. Alternatively you could rename it, so that
"type 1 = potentially usable maybe" so that beginners realise they're
screwed before they write their dodgy code... ;-)