[coreboot] [RFC][PATCH] v3: lar header after member support
Stefan Reinauer
stepan at coresystems.de
Fri Mar 28 10:33:38 CET 2008
Please dont do this. There's no reason to not just add a jump
instruction in front of an archive on architectures like mips and PPC
Also, NACK as long as the code adds #warnings instead of fixing issues.
Carl-Daniel Hailfinger wrote:
> We need this for MIPS.
>
> The patch already has an old
>
> Acked-by: Peter Stuge <peter at stuge.se>
>
> see Message-ID: <20071012093528.14814.qmail at stuge.se> for reference.
>
> Regards,
> Carl-Daniel
>
> On 05.12.2007 03:26, Carl-Daniel Hailfinger wrote:
>
>> We had that patch in a larger package about 7 weeks ago, but most parts
>> of the package have been merged since then, reducing the clutter in the
>> patch to zero. For your reference:
>> Message-ID: <470EA5CF.2020409 at gmx.net>
>> Date: Fri, 12 Oct 2007 00:38:07 +0200
>>
>> AFAIK not all architectures start executing code at the top of ROM, some
>> start at the bottom (low address). In that case, we can't start the
>> archive with a LAR header, but we can end it with one or postfix the
>> first archive member with a LAR header. To achieve that, the patch
>> redefines offset as signed instead of unsigned and allows the lar header
>> after the boot block to point to the boot block at the beginning. That
>> way, even bottom boot architectures can use the existing header format
>> unless the first LAR member is bigger than 2 GB.
>> This patch also introduces a 2 GB limit for file names in LARchives and
>> a 2 GB limit for unused space between header and data. There is no new
>> restriction for member lengths or archive length.
>>
>> Current LAR archives look like this:
>>
>> Hn=header n
>> -=padding
>> Dn=data n
>> H0D0D0D0H1D1----H2D2D2
>> where the last bytes of D2 are executed after poweron.
>>
>> The patch (together with signed offset) makes archives like the below
>> one possible:
>> D0D0D0H0H1D1----H2D2D2 (header after boot block points to boot block)
>>
>> The new archive format possibility allows placing a boot block at the
>> beginning without sacrificing the goal of one common archive format.
>> However, there are two potential problems:
>> - Endless loops if we aren't careful when walking the LAR. I think I got
>> all corner cases right.
>> - "Nobody will need more than 640kB", in our case it would be 2GB boot
>> blocks.
>>
>> Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006 at gmx.net>
>>
>>
>> Index: LinuxBIOSv3-larheaderaftermember/include/lar.h
>> ===================================================================
>> --- LinuxBIOSv3-larheaderaftermember/include/lar.h (Revision 539)
>> +++ LinuxBIOSv3-larheaderaftermember/include/lar.h (Arbeitskopie)
>> @@ -61,7 +61,15 @@
>> u32 reallen;
>> u32 checksum;
>> u32 compchecksum;
>> - u32 offset;
>> + /* The offset is signed to allow header after data for the first member
>> + * of the LAR. This is needed if code execution starts at bottom of
>> + * flash instead of at top of flash (x86). Please note that a
>> + * header-after-data LAR member can't be larger than 2^31 bytes.
>> + * Right now, we are about five orders of magnitude away from such a
>> + * beast.
>> + * Filenames are limited to 2^31-1-sizeof(lar_header)-1 bytes.
>> + * "Nobody will ever need more than 640k" */
>> + s32 offset;
>> /* Compression:
>> * 0 = no compression
>> * 1 = lzma
>> Index: LinuxBIOSv3-larheaderaftermember/lib/lar.c
>> ===================================================================
>> --- LinuxBIOSv3-larheaderaftermember/lib/lar.c (Revision 539)
>> +++ LinuxBIOSv3-larheaderaftermember/lib/lar.c (Arbeitskopie)
>> @@ -116,7 +116,9 @@
>>
>> if (strcmp(fullname, filename) == 0) {
>> printk(BIOS_SPEW, "LAR: CHECK %s @ %p\n", fullname, header);
>> - result->start = walk + ntohl(header->offset);
>> + /* In the header-before-member case offset is at least
>> + * sizeof(header) + strlen(filename) + 1 */
>> + result->start = walk + (s32)ntohl(header->offset);
>> result->len = ntohl(header->len);
>> result->reallen = ntohl(header->reallen);
>> result->compression = ntohl(header->compression);
>> @@ -137,9 +139,30 @@
>> * In the case of consecutive archive members with header-
>> * before-member structure, the next iteration of the loop will
>> * start exactly at the beginning of the next header.
>> - */
>> + * In the case of header-after-member (e.g. for bottom boot
>> + * architectures) the calculation below will effectively cause
>> + * walk < header. To elaborate a bit more, in this case
>> + * (header->offset + header->len - 1) will evaluate to a value
>> + * between -1 (header directly after file), -16 (file, 15 bytes
>> + * pad, header), and even smaller values if there is 16 bytes
>> + * or more of padding between member and header. The outer
>> + * expression will usually evaluate to 0xfffffff0, cause the
>> + * expected overflow with unsigned arithmetic and result in a
>> + * decrease of walk. That condition can be checked. */
>> +#warning FIXME: This loop will explode if this code is ever compiled in 64bit mode
>> +#warning because of the hardcoded 0xfffffff0.
>> walk += (ntohl(header->offset) + ntohl(header->len) - 1)
>> & 0xfffffff0;
>> + /* If we have header-after-member, walk < header is true.
>> + * Go forward instead by starting at header, adding header size
>> + * and strlen(fullname). The result of this calculation is the
>> + * position of the terminating \0 of fullname. Round that
>> + * address down to the next 16 byte boundary. */
>> + if (walk < (char *)header) {
>> + walk = (char *)header;
>> + walk += (sizeof(struct lar_header) + strlen(fullname))
>> + & 0xfffffff0;
>> + }
>> }
>> printk(BIOS_SPEW, "LAR: File not found!\n");
>> return 1;
>> Index: LinuxBIOSv3-larheaderaftermember/util/lar/lar.h
>> ===================================================================
>> --- LinuxBIOSv3-larheaderaftermember/util/lar/lar.h (Revision 539)
>> +++ LinuxBIOSv3-larheaderaftermember/util/lar/lar.h (Arbeitskopie)
>> @@ -60,6 +60,7 @@
>> typedef uint64_t u64;
>> typedef uint32_t u32;
>> typedef uint8_t u8;
>> +typedef int32_t s32;
>>
>> /* NOTE -- This and the user-mode lar.h may NOT be in sync. Be careful. */
>> struct lar_header {
>> @@ -68,9 +69,15 @@
>> u32 reallen;
>> u32 checksum;
>> u32 compchecksum;
>> - /* Filenames are limited to 2^31-1-sizeof(lar_header)-1 bytes.
>> + /* The offset is signed to allow header after data for the first member
>> + * of the LAR. This is needed if code execution starts at bottom of
>> + * flash instead of at top of flash (x86). Please note that a
>> + * header-after-data LAR member can't be larger than 2^31 bytes.
>> + * Right now, we are about five orders of magnitude away from such a
>> + * beast.
>> + * Filenames are limited to 2^31-1-sizeof(lar_header)-1 bytes.
>> * "Nobody will ever need more than 640k" */
>> - u32 offset;
>> + s32 offset;
>> /* Compression:
>> * 0 = no compression
>> * 1 = lzma
>>
>
>
More information about the coreboot
mailing list