Fill out ChromeOS specific coreboot table extensions
[coreboot.git] / src / arch / x86 / lib / walkcbfs.S
1 #define CBFS_HEADER_PTR 0xfffffffc
2
3 #define CBFS_HEADER_MAGIC 0
4 #define CBFS_HEADER_VERSION (CBFS_HEADER_MAGIC + 4)
5 #define CBFS_HEADER_ROMSIZE (CBFS_HEADER_VERSION + 4)
6 #define CBFS_HEADER_BOOTBLOCKSIZE (CBFS_HEADER_ROMSIZE + 4)
7 #define CBFS_HEADER_ALIGN (CBFS_HEADER_BOOTBLOCKSIZE + 4)
8 #define CBFS_HEADER_OFFSET (CBFS_HEADER_ALIGN + 4)
9
10 #define CBFS_FILE_MAGIC 0
11 #define CBFS_FILE_LEN (CBFS_FILE_MAGIC + 8)
12 #define CBFS_FILE_TYPE (CBFS_FILE_LEN + 4)
13 #define CBFS_FILE_CHECKSUM (CBFS_FILE_TYPE + 4)
14 #define CBFS_FILE_OFFSET (CBFS_FILE_CHECKSUM + 4)
15
16 #define CBFS_FILE_STRUCTSIZE (CBFS_FILE_OFFSET + 4)
17
18 /*
19  * input %esi: filename
20  * input %esp: return address (not pointer to return address!)
21  * output %eax: entry point
22  * clobbers %ebx, %ecx, %edi
23  */
24 walkcbfs_asm:
25         cld
26
27         mov CBFS_HEADER_PTR, %eax
28         mov CBFS_HEADER_ROMSIZE(%eax), %ecx
29         bswap %ecx
30         mov $0, %ebx
31         sub %ecx, %ebx  /* rom base address in ebx */
32         mov CBFS_HEADER_OFFSET(%eax), %ecx
33         bswap %ecx
34         add %ecx, %ebx  /* address where we start looking for LARCHIVEs */
35
36         /* determine filename length */
37         mov $0, %eax
38 1:
39         cmpb $0, (%eax,%esi)
40         jz 2f
41         add $1, %eax
42         jmp 1b
43 2:
44         add $1, %eax
45 walker:
46         mov 0(%ebx), %edi /* Check for LARCHIVE header */
47         cmp %edi, filemagic
48         jne searchfile
49         mov 4(%ebx), %edi
50         cmp %edi, filemagic+4
51         jne searchfile
52
53         /* LARCHIVE header found */
54         mov %ebx, %edi
55         add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */
56         mov %eax, %ecx
57         repe cmpsb
58         /* zero flag set if strings are equal */
59         jnz tryharder
60
61         /* we found it! */
62         mov CBFS_FILE_OFFSET(%ebx), %eax
63         bswap %eax
64         add %ebx, %eax
65         jmp *%esp
66
67 tryharder:
68         sub %ebx, %edi
69         sub $CBFS_FILE_STRUCTSIZE, %edi /* edi = # of walked bytes */
70         sub %edi, %esi /* esi = start of filename */
71
72         /* ebx = ecx = (current+offset+len+ALIGN-1) & ~(ALIGN-1) */
73         mov CBFS_FILE_OFFSET(%ebx), %ecx
74         bswap %ecx
75         add %ebx, %ecx
76         mov CBFS_FILE_LEN(%ebx), %edi
77         bswap %edi
78         add %edi, %ecx
79         mov CBFS_HEADER_PTR, %edi
80         mov CBFS_HEADER_ALIGN(%edi), %edi
81         bswap %edi
82         sub $1, %edi
83         add %edi, %ecx
84         not %edi
85         and %edi, %ecx
86
87         /* if oldaddr >= addr, leave */
88         cmp %ebx, %ecx
89         jbe out
90
91         mov %ecx, %ebx
92
93 check_for_exit:
94         /* look if we should exit: did we pass into the bootblock already? */
95         mov CBFS_HEADER_PTR, %ecx
96         mov CBFS_HEADER_BOOTBLOCKSIZE(%ecx), %ecx
97         bswap %ecx
98         not %ecx
99         add $1, %ecx
100
101         cmp %ecx, %ebx
102         /* if bootblockstart >= addr (==we're still in the data area) , jump back */
103         jbe walker
104
105 out:
106         mov $0, %eax
107         jmp *%esp
108
109
110 searchfile:
111         /* if filemagic isn't found, move forward cbfs_header->align bytes */
112         mov CBFS_HEADER_PTR, %edi
113         mov CBFS_HEADER_ALIGN(%edi), %edi
114         bswap %edi
115         add %edi, %ebx
116         jmp check_for_exit
117
118 filemagic:
119         .ascii "LARCHIVE"