Two hda_verb.h files: Add more comments.
[coreboot.git] / src / arch / i386 / 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 #define CBFS_STAGE_COMPRESSION 0
19 #define CBFS_STAGE_ENTRY (CBFS_STAGE_COMPRESSION + 4)
20 #define CBFS_STAGE_LOAD (CBFS_STAGE_ENTRY + 8)
21 #define CBFS_STAGE_LEN (CBFS_STAGE_LOAD + 8)
22 #define CBFS_STAGE_MEMLEN (CBFS_STAGE_LEN + 4)
23
24 /*
25   input %esi: filename
26   input %esp: return address (not pointer to return address!)
27   output %eax: entry point
28   clobbers %ebx, %ecx, %edi
29 */
30 walkcbfs:
31         cld
32
33         mov CBFS_HEADER_PTR, %eax
34         mov CBFS_HEADER_ROMSIZE(%eax), %ecx
35         bswap %ecx
36         mov $0, %ebx
37         sub %ecx, %ebx
38         mov CBFS_HEADER_OFFSET(%eax), %ecx
39         bswap %ecx
40         add %ecx, %ebx
41
42         /* determine filename length */
43         mov $0, %eax
44 1:
45         cmpb $0, (%eax,%esi)
46         jz 2f
47         add $1, %eax
48         jmp 1b
49 2:
50         add $1, %eax
51 walker:
52         mov 0(%ebx), %edi
53         cmp %edi, filemagic
54         jne searchfile
55         mov 4(%ebx), %edi
56         cmp %edi, filemagic+4
57         jne searchfile
58
59         mov %ebx, %edi
60         add $CBFS_FILE_STRUCTSIZE, %edi /* edi = address of first byte after struct cbfs_file */
61         mov %eax, %ecx
62         repe cmpsb
63         # zero flag set if strings are equal
64         jnz tryharder
65
66         # we found it!
67         mov CBFS_FILE_OFFSET(%ebx), %eax
68         bswap %eax
69         add %ebx, %eax
70         add $CBFS_STAGE_ENTRY, %eax /* eax = ((cbfs_stage* (cbfs_file* ebx)->offset)->entry) */
71         mov 0(%eax), %eax
72         jmp *%esp
73
74 tryharder:
75         sub %ebx, %edi
76         sub $CBFS_FILE_STRUCTSIZE, %edi /* edi = # of walked bytes */
77         sub %edi, %esi /* esi = start of filename */
78
79         /* ebx = ecx = (current+offset+len+ALIGN-1) & ~(ALIGN-1) */
80         mov CBFS_FILE_OFFSET(%ebx), %ecx
81         bswap %ecx
82         add %ebx, %ecx
83         mov CBFS_FILE_LEN(%ebx), %edi
84         bswap %edi
85         add %edi, %ecx
86         mov CBFS_HEADER_PTR, %edi
87         mov CBFS_HEADER_ALIGN(%edi), %edi
88         bswap %edi
89         sub $1, %edi
90         add %edi, %ecx
91         not %edi
92         and %edi, %ecx
93
94         /* if oldaddr >= addr, leave */
95         cmp %ebx, %ecx
96         jbe out
97
98         mov %ecx, %ebx
99
100 check_for_exit:
101         /* look if we should exit: did we pass into the bootblock already? */
102         mov CBFS_HEADER_PTR, %ecx
103         mov CBFS_HEADER_BOOTBLOCKSIZE(%ecx), %ecx
104         bswap %ecx
105         not %ecx
106         add $1, %ecx
107
108         cmp %ecx, %ebx
109         /* if bootblockstart >= addr (==we're still in the data area) , jump back */
110         jbe walker
111
112 out:
113         mov $0, %eax
114         jmp *%esp
115
116
117 searchfile:
118         /* if filemagic isn't found, move forward cbfs_header->align bytes */
119         mov CBFS_HEADER_PTR, %edi
120         mov CBFS_HEADER_ALIGN(%edi), %edi
121         bswap %edi
122         add %edi, %ebx
123         jmp check_for_exit
124
125 filemagic:
126         .ascii "LARCHIVE"