summaryrefslogtreecommitdiff
path: root/src/arch/i386/lib
diff options
context:
space:
mode:
authorPatrick Georgi <patrick.georgi@coresystems.de>2009-12-23 12:52:56 +0000
committerPatrick Georgi <patrick.georgi@coresystems.de>2009-12-23 12:52:56 +0000
commit9341acda13aa2e8d8df4f04f80c14ace52f9aa27 (patch)
tree5b65f3604728fcc7a3b0ce061290af9bae0ff14f /src/arch/i386/lib
parent336daa76faa6255cf487100a9741c740802bb32f (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.S94
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