Hi,
Some suggestions:
1) We could put a checksum in the LinuxBIOS rom image so it can be checked for integrity during boot time. Usually safety relevant embedded devices require such a checksum and use CRC16 or CRC32 for that.
2) Is there any distinct way of finding out whether a flash image is a LinuxBIOS image? One thing that can be read from an image is the mainboard vendor and id, but the code looks somewhat ugly:
void show_id(unsigned char *bios, int size) { unsigned char *manuf, *id;
id=bios+size-0x1d; while (*id==0) id--; while (*id) id--;
manuf=id-1; id++; while (*manuf && *manuf!=0xff) manuf--; manuf++;
printf("MANUFACTURER: %s\n", manuf); printf("MAINBOARD ID: %s\n", id); }
3) There should be a flash description map in the rom file that allows a program accessing the flash to automatically exclude certain flashing areas such as the onboard option rom space or the fallback image.
Stefan
Stefan Reinauer stepan@openbios.org writes:
Hi,
Some suggestions:
- We could put a checksum in the LinuxBIOS rom image so it can be checked for integrity during boot time. Usually safety relevant embedded devices require such a checksum and use CRC16 or CRC32 for that.
That sounds sane, at least in principle.
Is there any distinct way of finding out whether a flash image is a LinuxBIOS image? One thing that can be read from an image is the mainboard vendor and id, but the code looks somewhat ugly:
void show_id(unsigned char *bios, int size) { unsigned char *manuf, *id;
id=bios+size-0x1d; while (*id==0) id--; while (*id) id--; manuf=id-1; id++; while (*manuf && *manuf!=0xff) manuf--; manuf++; printf("MANUFACTURER: %s\n", manuf); printf("MAINBOARD ID: %s\n", id);
}
We have on most boards id.lds That places that information at a magic location. Unfortunately that conflicts with nvidia chipset requirements. And I think in the general case and fixed location will be a problem.
- There should be a flash description map in the rom file that allows a program accessing the flash to automatically exclude certain flashing areas such as the onboard option rom space or the fallback image.
Again in principle I agree.
My basic concern is that I don't think we can do this inline across variations in architecture. Although I don't have a problem exporting such information from the linuxbios table which should work universally but it won't work for the first we flash something.
Please checkout our latest version of lbflash ftp://ftp.lnxi.com/pub/linuxbios/utilities/lbflash/
We have a working map. The code works well enough that we can deal with multiple flash chips and other weird cases automatically.
Things like not flashing the fallback image by default we have been doing for a long time. Being able to just flash the bootloader/payload we are just starting to do but the structure is there.
The ideal case is if we could start converging flash_and_burn and lbflash. At least with respect to user interface.
The case that isn't currently covered is a checksum and that is only because it keeps slipping my mind. We do perform a full byte for byte comparison against the source file though. Which is good to ensure you have flashed successfully but it doesn't detect if your romimage got damaged in transport.
Eric
* Eric W. Biederman ebiederman@lnxi.com [051112 22:27]:
void show_id(unsigned char *bios, int size) { unsigned char *manuf, *id; id=bios+size-0x1d; while (*id==0) id--; while (*id) id--; manuf=id-1; id++; while (*manuf && *manuf!=0xff) manuf--; manuf++; printf("MANUFACTURER: %s\n", manuf); printf("MAINBOARD ID: %s\n", id); }
We have on most boards id.lds That places that information at a magic location. Unfortunately that conflicts with nvidia chipset requirements. And I think in the general case and fixed location will be a problem.
The above will fail on nvidia. Agreed.
The next problem is that the id is relative to the end of the image. So the start position changes a) dependent on the chipset b) dependent on the length of the motherboard manufacturer and id.
NVIDIA:
SECTIONS { . = (_ROMBASE + ROM_IMAGE_SIZE - 0x80) - (__id_end - __id_start); .id (.): { *(.id) } }
Others (src/arch/i386/lib/id.lds) SECTIONS { . = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start); .id (.): { *(.id) } }
the arima hdama image looks like this: 00000000fffdffd8 R __id_start 00000000fffdffd8 r vendor 00000000fffdffde r part 00000000fffdfff0 R __id_end
only the last 16 bytes don't belong to the ID.
funny enough, linuxbios.rom contains this:
007ffd0: ffff ffff ffff ffff 4152 494d 4100 4844 ........ARIMA.HD 007ffe0: 414d 4100 2800 0000 2200 0000 0000 0200 AMA.(..."....... 007fff0: e9b5 49ff ff00 0000 e903 4aff ff00 0000 ..I.......J.....
So where does the 2800 0000 2200 0000 0000 0200 come from?
Does the linker put some crap in there after the ID?
This makes it really hard to do a decent identification, even if we know where the ID should/could be.
I would also suggest that on a given cpu architecture (ie. x86 or ppc) the ID string should either be at a fixed address, one that suits all chipsets. Or It should be identifyable in flash using a signature, similar to the LinuxBIOS table in memory.
My basic concern is that I don't think we can do this inline across variations in architecture.
If such a in-rom table differs in position or details between x86 and ppc, this won't be too nasty.
Although I don't have a problem exporting such information from the linuxbios table which should work universally but it won't work for the first we flash something.
I agree. Putting this in the LinuxBIOS table would be fine to probe the running system. I rather plan for the case where there has never been a time with a non-linuxbios image in flash.
Please checkout our latest version of lbflash ftp://ftp.lnxi.com/pub/linuxbios/utilities/lbflash/
We have a working map. The code works well enough that we can deal with multiple flash chips and other weird cases automatically.
I've looked at this. Do you deliver this map as an extra file with an image? Having this in the image would help comparing the map of an file image to that of the rom image for example. I.e. you have two versions of a board out there, one with 8MBit flash and one with 4 MBit flash. Someone has a 512kByte flash file. Is this the normal image of case 1 or a complete image of case 2 etc pp.
I'd rather give them a cat rommap linuxbios.rom > linuxbios.flashimage than 2 different files to cope with because I bet someone will mix this up some time. It's just not solid.
The ideal case is if we could start converging flash_and_burn and lbflash. At least with respect to user interface.
I've looked at lbflash earlier today. It seems to be using mtd for all it's actions while flash_and_burn uses /dev/mem and some extra magic. Then there's my old and obsolete /dev/bios. I want to drop that one at least and rather have an improved solution in userspace.
MTD is overly complex for what we are doing. and flash_and_burn has been working really reliably for me.
I also saw you have a newer lbflash version available as a binary than as source. Unfortunately there's no changelog in the binary rpm. Is it worth waiting for that source release?
The case that isn't currently covered is a checksum and that is only because it keeps slipping my mind. We do perform a full byte for byte comparison against the source file though. Which is good to ensure you have flashed successfully but it doesn't detect if your romimage got damaged in transport.
In safety critical environments a system is required to deny service if it can't proof it's own integrity during runtime. Lots of systems even probe flash and memory continuedly during runtime to find bit tilts within a really short manifestation time.
Stefan.
Stefan Reinauer stepan@openbios.org writes:
The above will fail on nvidia. Agreed.
The next problem is that the id is relative to the end of the image. So the start position changes a) dependent on the chipset b) dependent on the length of the motherboard manufacturer and id.
NVIDIA:
SECTIONS { . = (_ROMBASE + ROM_IMAGE_SIZE - 0x80) - (__id_end - __id_start); .id (.): { *(.id) } }
Others (src/arch/i386/lib/id.lds) SECTIONS { . = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start); .id (.): { *(.id) } }
the arima hdama image looks like this: 00000000fffdffd8 R __id_start 00000000fffdffd8 r vendor 00000000fffdffde r part 00000000fffdfff0 R __id_end
only the last 16 bytes don't belong to the ID.
funny enough, linuxbios.rom contains this:
007ffd0: ffff ffff ffff ffff 4152 494d 4100 4844 ........ARIMA.HD 007ffe0: 414d 4100 2800 0000 2200 0000 0000 0200 AMA.(..."....... 007fff0: e9b5 49ff ff00 0000 e903 4aff ff00 0000 ..I.......J.....
So where does the 2800 0000 2200 0000 0000 0200 come from?
Does the linker put some crap in there after the ID?
This makes it really hard to do a decent identification, even if we know where the ID should/could be.
I don't recall exactly but look at the code in lbflash does. I believe there is a pointer to where the vendor and part are.
I would also suggest that on a given cpu architecture (ie. x86 or ppc) the ID string should either be at a fixed address, one that suits all chipsets. Or It should be identifyable in flash using a signature, similar to the LinuxBIOS table in memory.
The problem is that over time hardware people get inventive. So I'm not certain that is possible.
My basic concern is that I don't think we can do this inline across variations in architecture.
If such a in-rom table differs in position or details between x86 and ppc, this won't be too nasty.
Agreed. But having code that works everywhere is useful.
Although I don't have a problem exporting such information from the linuxbios table which should work universally but it won't work for the first we flash something.
I agree. Putting this in the LinuxBIOS table would be fine to probe the running system. I rather plan for the case where there has never been a time with a non-linuxbios image in flash.
Agreed.
Please checkout our latest version of lbflash ftp://ftp.lnxi.com/pub/linuxbios/utilities/lbflash/
We have a working map. The code works well enough that we can deal with multiple flash chips and other weird cases automatically.
I've looked at this. Do you deliver this map as an extra file with an image?
Yes. There is a directory with all of that.
Having this in the image would help comparing the map of an file image to that of the rom image for example. I.e. you have two versions of a board out there, one with 8MBit flash and one with 4 MBit flash. Someone has a 512kByte flash file. Is this the normal image of case 1 or a complete image of case 2 etc pp.
Right now as long as the image is small enough it fits in 4Mbit it will happily flash in either a 4Mbit or an 8Mbit part.
I'd rather give them a cat rommap linuxbios.rom > linuxbios.flashimage than 2 different files to cope with because I bet someone will mix this up some time. It's just not solid.
Yes and no. Having a directory with all of the pieces is useful, and is a lot more maintainable from a forward/backwards compatibility point of view. If we combine them I would rather do it as a cpio or a tar or an rpm. Something where the structure is apparent but you have to try to work at it to get multiple files.
The ideal case is if we could start converging flash_and_burn and lbflash. At least with respect to user interface.
I've looked at lbflash earlier today. It seems to be using mtd for all it's actions while flash_and_burn uses /dev/mem and some extra magic. Then there's my old and obsolete /dev/bios. I want to drop that one at least and rather have an improved solution in userspace.
MTD is overly complex for what we are doing. and flash_and_burn has been working really reliably for me.
I am conflicted on that one. If you are talking users and not developers it is usually easier to ensure that people have the right mtd drivers loaded. Last I looked the mtd code had a much better structure than flash_and_burn, allowing for much more code reuse and a lot more eyes looking at the problems. flash_and_burn on the other hand seems a great tool for developers, who know what should be happening but it doesn't seem to have as many checks to make certain that you aren't doing something stupid.
I also saw you have a newer lbflash version available as a binary than as source. Unfortunately there's no changelog in the binary rpm. Is it worth waiting for that source release?
Groan. It looks like someone forget to place the source rpm on the public ftp site. 2.1 is pretty much a maintenance release with the exception of a couple of very minor bug fixes nothing really has changed. So for getting a feel of the structure and the files we are currently using 2.0 should be reasonable starting point.
The case that isn't currently covered is a checksum and that is only because it keeps slipping my mind. We do perform a full byte for byte comparison against the source file though. Which is good to ensure you have flashed successfully but it doesn't detect if your romimage got damaged in transport.
In safety critical environments a system is required to deny service if it can't proof it's own integrity during runtime. Lots of systems even probe flash and memory continuedly during runtime to find bit tilts within a really short manifestation time.
Sure I don't have a problem with putting a checksum, crc or a hash in a data segment somewhere. It will likely take an extra linker pass to do that but that shouldn't be a problem. Ideally that would be one of the triggers for deciding if we go to fallback or normal mode.
Hmm. In looking at things I just noticed that the decompressor doesn't have anything like that, which really is a bug. That I unfortunately didn't catch when I found that code.
Eric
* Eric W. Biederman ebiederman@lnxi.com [051113 09:33]:
Others (src/arch/i386/lib/id.lds) SECTIONS { . = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start); .id (.): { *(.id) } }
the arima hdama image looks like this: 00000000fffdffd8 R __id_start 00000000fffdffd8 r vendor 00000000fffdffde r part 00000000fffdfff0 R __id_end
only the last 16 bytes don't belong to the ID.
funny enough, linuxbios.rom contains this:
007ffd0: ffff ffff ffff ffff 4152 494d 4100 4844 ........ARIMA.HD 007ffe0: 414d 4100 2800 0000 2200 0000 0000 0200 AMA.(..."....... 007fff0: e9b5 49ff ff00 0000 e903 4aff ff00 0000 ..I.......J.....
So where does the 2800 0000 2200 0000 0000 0200 come from?
Does the linker put some crap in there after the ID?
Looking at crt0.s it is not crap but really useful: The linker places pointers to the string so we actually don't have to walk backward. I could not find this in the code, but I consider it can be used:
int show_id(unsigned char *bios, int size) { unsigned char *manuf, *id; unsigned int *walk;
walk=(unsigned int *)(bios+size-0x10); walk--; printf("image size=%d\n", *walk); walk--; id=bios+size-*walk; walk--; manuf=bios+size-*walk; printf("MANUFACTURER: %s\n", manuf); printf("MAINBOARD ID: %s\n", id); return 0; }
I would also suggest that on a given cpu architecture (ie. x86 or ppc) the ID string should either be at a fixed address, one that suits all chipsets. Or It should be identifyable in flash using a signature, similar to the LinuxBIOS table in memory.
The problem is that over time hardware people get inventive. So I'm not certain that is possible.
Though, matching a file image with what is in a certain system is absolutely necessary if we want to establish LinuxBIOS as a usable product for end customers.
If such a in-rom table differs in position or details between x86 and ppc, this won't be too nasty.
Agreed. But having code that works everywhere is useful.
There will always be small differences, such where the image is located and where the entry point is loaded. As long as there's a good mechanism making it easy to get this information in one way we're fine. The LinuxBIOS table is slightly different on ppc and x86 already today.
Having this in the image would help comparing the map of an file image to that of the rom image for example. I.e. you have two versions of a board out there, one with 8MBit flash and one with 4 MBit flash. Someone has a 512kByte flash file. Is this the normal image of case 1 or a complete image of case 2 etc pp.
Right now as long as the image is small enough it fits in 4Mbit it will happily flash in either a 4Mbit or an 8Mbit part.
So you could flash a fallback only image over a fallback+normal image without lbflash ever complaining.
Yes and no. Having a directory with all of the pieces is useful, and is a lot more maintainable from a forward/backwards compatibility point of view. If we combine them I would rather do it as a cpio or a tar or an rpm. Something where the structure is apparent but you have to try to work at it to get multiple files.
Probably true.
I am conflicted on that one. If you are talking users and not developers it is usually easier to ensure that people have the right mtd drivers loaded. Last I looked the mtd code had a much better structure than flash_and_burn, allowing for much more code reuse and a lot more eyes looking at the problems. flash_and_burn on the other hand seems a great tool for developers, who know what should be happening but it doesn't seem to have as many checks to make certain that you aren't doing something stupid.
I would agree if mtd did the autoprobing and flash_and_burn didnt. But finding the right pair of mtd drivers can be annoying. The modular concept is nice, no doubt. But for an end user I don't really see an advantage.
Groan. It looks like someone forget to place the source rpm on the public ftp site. 2.1 is pretty much a maintenance release with the exception of a couple of very minor bug fixes nothing really has changed. So for getting a feel of the structure and the files we are currently using 2.0 should be reasonable starting point.
Ah, I assumed that you would only provide the source for older releases, same for the cmos tool. Which would be perfectly understandable. So I will have a closer look at lbflash. How do you produce the rom tables?
Hmm. In looking at things I just noticed that the decompressor doesn't have anything like that, which really is a bug. That I unfortunately didn't catch when I found that code.
Hey, it's really small. In a safety critical application we might not even want to go to fallback mode but rather print an error message over serial and go to nirvana in case of a wrong checksum. Just wondering where the best place for such a checksum check would be anyways. I would not want to cope with this in ramless code I guess.
Stefan