diff options
author | Patrick Georgi <patrick.georgi@coresystems.de> | 2009-12-23 12:52:56 +0000 |
---|---|---|
committer | Patrick Georgi <patrick.georgi@coresystems.de> | 2009-12-23 12:52:56 +0000 |
commit | 9341acda13aa2e8d8df4f04f80c14ace52f9aa27 (patch) | |
tree | 5b65f3604728fcc7a3b0ce061290af9bae0ff14f /src/arch/i386/lib | |
parent | 336daa76faa6255cf487100a9741c740802bb32f (diff) |
Tiny Bootblock, step 1/n.
Introduce the tiny bootblock infrastructure and use it on QEmu.
Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
Acked-by: Myles Watson <mylesgw@gmail.com>
Acked-by: Ronald G. Minnich <rminnich@gmail.com>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4989 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386/lib')
-rw-r--r-- | src/arch/i386/lib/walkcbfs.S | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/arch/i386/lib/walkcbfs.S b/src/arch/i386/lib/walkcbfs.S new file mode 100644 index 0000000000..aba0453d1f --- /dev/null +++ b/src/arch/i386/lib/walkcbfs.S @@ -0,0 +1,94 @@ +#define CBFS_HEADER_PTR 0xfffffffc + +#define CBFS_HEADER_MAGIC 0 +#define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4) +#define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4) +#define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4) +#define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4) +#define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4) + +#define CBFS_FILE_MAGIC 0 +#define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8) +#define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4) +#define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4) +#define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4) + +#define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4) + +#define CBFS_STAGE_COMPRESSION 0 +#define CBFS_STAGE_ENTRY (CBFS_STAGE_COMPRESSION + 4) +#define CBFS_STAGE_LOAD (CBFS_STAGE_ENTRY + 8) +#define CBFS_STAGE_LEN (CBFS_STAGE_LOAD + 8) +#define CBFS_STAGE_MEMLEN (CBFS_STAGE_LEN + 4) + +/* + input %esi: filename + input %esp: return address (not pointer to return address!) + output %eax: entry point + clobbers %ebx, %ecx, %edx, %edi, %ebp +*/ +walkcbfs: + mov %esi, %ebp /* stash away filename pointer */ + mov $0, %edx +1: + cmpb $0, (%edx,%esi) + jz 2f + add $1, %edx + jmp 1b +2: + add $1, %edx + mov CBFS_HEADER_PTR, %eax + mov CBFS_HEADER_ROMSIZE(%eax), %ecx + bswap %ecx + mov $0, %ebx + sub %ecx, %ebx + mov CBFS_HEADER_OFFSET(%eax), %ecx + bswap %ecx + add %ecx, %ebx + mov CBFS_HEADER_ALIGN(%eax), %eax + bswap %eax + sub $1, %eax + +walker: + mov %ebp, %esi + mov %ebx, %edi + add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */ + mov %edx, %ecx + repe cmpsb + # zero flag set if strings are equal + jnz tryharder + + # we found it! + mov CBFS_FILE_OFFSET(%ebx), %eax + bswap %eax + add %ebx, %eax + add $CBFS_STAGE_ENTRY, %eax /* eax = ((cbfs_stage* (cbfs_file* ebx)->offset)->entry) */ + mov 0(%eax), %eax + jmp *%esp + +tryharder: + mov CBFS_FILE_OFFSET(%ebx), %ecx + bswap %ecx + add %ebx, %ecx + mov CBFS_FILE_LEN(%ebx), %edi + bswap %edi + add %edi, %ecx + add %eax, %ecx + mov %eax, %edi + not %edi + and %edi, %ecx + mov %ecx, %ebx + + /* look if we should exit */ + mov CBFS_HEADER_PTR, %esi + mov CBFS_HEADER_ROMSIZE(%esi), %ecx + bswap %ecx + not %ecx + add $1, %ecx + + cmp %ebx, %ecx + /* if we're still inside the ROM area, jump back */ + jbe walker + + mov $0, %eax + jmp *%esp |