Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / llfw / romfs.S
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 #include "macros.h"
13 #include "romfs.h"
14
15 /*******************************************************************
16  * Wrapper for romfs_lookup.
17  *
18  * Input:
19  * R3 = address of filename string
20  * R4 = address of struct romfs_t
21  *               0: file size (return)
22  *               8: flags     (return)
23  *              10: fileaddr  (return and input: tells if first search)
24  *              18: nextfile  (return)
25  *              20: namep     (return)
26  *
27  * Find File Procedure
28  * - set filename and rombase, on return 0 file properties are stored
29  *   in romfs_t else struct not valid
30  * 
31  * Listing procedure
32  * - clear romfs_t (important!)
33  * - set filename = NULL and rombase and call returns first file 
34  *   with properties in romfs_t including next-file pointer
35  * - if nextpointer is non-zero then just the next file is returned
36  *
37  * Returns:
38  * <Success>: 
39  *      R3 = 0
40  *      romfs_t is updated
41  * <FileNotFound>:
42  *      R3 = 1
43  *      romfs_t not touched
44  *
45  * Potentially modifies the following registers:
46  *
47  
48  Example usage from C:
49
50   int list_bootrom()
51   {
52         struct romfs_t rfs;
53         int i;
54
55         printf("Build: "__TIME__" "__DATE__" \n");
56
57         i = 0;
58         memset((void*) &rfs, 0, sizeof(struct romfs_t));
59         printf("         No. File      Data          Size  Name\n");
60
61         while (romfs_stat(NULL, &rfs) == 0) {
62                 i++;
63                 printf("         %02d: %08X  %08X   %7d  %s\n",
64                                 i, rfs.fileaddr, rfs.datap, 
65                                 rfs.size, rfs.namep);
66         }
67         if (0 == i) {
68                 printf("Error in reading ROMFS\n");
69                 return 1;
70         }
71         return 0;
72   }
73  *******************************************************************/
74 #define RFS_T_SIZE      0x00
75 #define RFS_T_FLAGS     0x08
76 #define RFS_T_FILEADDR  0x10
77 #define RFS_T_NEXT      0x18
78 #define RFS_T_NAME      0x20
79 #define RFS_T_DATA      0x28
80
81 #define RFS_H_NEXT      0x00
82 #define RFS_H_SIZE      0x08
83 #define RFS_H_FLAGS     0x10
84 #define RFS_H_DATA      0x18
85 #define RFS_H_NAME      0x20
86
87 ENTRY(romfs_stat_file)
88         /* save link register and romfs_t pointer         */
89         mflr    r15
90         mr      r16, r4
91
92         /* if filename R3 is 0 then its a listing request */
93         /* if not then just continue to lookup name       */
94         /* save R4 to R8 which is the address of header   */
95         li      r7, 0
96         cmpd    r3, r7
97         beq     romfs_list
98         bl      romfs_lookup
99         mfsprg  r8, 1
100
101         /* if file found then go to romfs_fill_properties */
102         /* else return 1 to caller                        */
103         cmpwi   r3, 0
104         beq     romfs_fill_properties
105         b       romfs_stat_end
106
107   romfs_list:
108         /* check if fileaddr == 0, in this case its       */
109         /* the first search on this handle, so return all */
110         /* info for file at rombase (R8=R4)               */
111         ld      r6, RFS_T_FILEADDR(r4)
112         mfsprg  r8, 1
113         li      r7, 0
114         cmpd    r7, r6
115         beq     romfs_fill_properties
116
117         /* check if next file != 0   by looking into      */
118         /* romfs_t, if not then return (next = 0) 1       */
119         li      r7, 0
120         ld      r4, RFS_T_NEXT(r4)
121         cmpd    r7, r4
122         li      r3, 1
123         beq     romfs_stat_end
124
125         /* now next file is available so move R8 to next  */
126         /* file address                                   */
127         mr      r8, r4
128
129   romfs_fill_properties:
130         /* set properties in romfs_t takes R8 as address  */
131         /* to file header and R16 as address of romfs_t   */
132         mfsprg  r3, 1
133         std     r8, RFS_T_FILEADDR(r16)
134
135         ld      r4, RFS_H_NEXT(r8)
136         li      r7, 0
137         cmpd    r7, r4
138         beq     $ + (2 * 4) /* =0 so add no rombase */
139         add     r4, r4, r3
140         std     r4, RFS_T_NEXT(r16)
141
142         ld      r4, RFS_H_SIZE(r8)
143         std     r4, RFS_T_SIZE(r16)
144         ld      r4, RFS_H_FLAGS(r8)
145         std     r4, RFS_T_FLAGS(r16)
146
147         ld      r4, RFS_H_DATA(r8)
148         add     r4, r4, r3
149         std     r4, RFS_T_DATA(r16)
150
151         addi    r4, r8, RFS_H_NAME
152         std     r4, RFS_T_NAME(r16)
153
154         li      r3, 0
155
156         /* restore romfs_t pointer and link register      */
157   romfs_stat_end:
158         mr      r5, r16
159         mtlr    r15
160         blr
161
162 /*******************************************************************
163  * Copies the data of file referenced by name string to address 
164  * requires root address of filesystem.
165  * FIXME: ignores flags
166  *
167  * Input:
168  * R3 = address of filename string
169  * R4 = ROMBASE
170  * R5 = destination address
171  *
172  * Returns:
173  * <Success>: R3 = 0, R6 = size, <FileNotFound>: R3 = 1
174  * R5 is kept
175  *  
176  * Potentially modifies the following registers:
177  * ctr, r15, r16, r17, r18
178  * 
179  * Uses the following calls with subsequent register modification:
180  * - romfs_lookup
181  *******************************************************************/
182 ASM_ENTRY(romfs_load)
183         mflr    r15
184         
185         /* save R5 twice              */
186         /* lookup file, input regs    */
187         /* are already set            */
188         /* if not found, just return  */
189         mr      r16, r5
190         mr      r17, r5
191         bl      romfs_lookup
192         cmpwi   r3, 1
193         bne     0f
194         mtlr    r15
195         blr     /* abort, not found   */
196
197         /* save data size for return  */
198         /* found, copy data           */
199         /* data size is in R6         */
200 0:
201         //mr    r3, r6
202         mtctr   r6
203         addi    r16, r16, -1 /* dest  */
204         addi    r5, r5, -1   /* source*/
205
206         /* data is expected to be     */
207         /* 8 byte aligned             */
208         /* copy loop                  */
209 0:      lbzu    r18, 1(r5)
210         stbu    r18, 1(r16)
211         bdnz    0b
212
213         /* restore size, keep padding */
214         /* restore target address     */
215         /* return                     */
216         mr      r5, r17
217         mtlr    r15
218         blr
219
220 /*******************************************************************
221  * looks up a file based on filename 
222  *
223  * Input:
224  * R3 = address of filename string
225  * R4 = ROMBASE
226  *
227  * Returns:
228  * <Success>: 
229  *      R3 = 0
230  *      R4 = address of file header
231  *      R5 = address of data (real address)
232  *      R6 = size of data
233  *      R7 = flags for file
234  * <FileNotFound>:
235  *      R3 = 1
236  *
237  * Potentially modifies the following registers:
238  * R3, R4, R5, R6, R7, R8, R9
239  * 
240  * Uses the following calls with subsequent register modification:
241  * - romfs_namematch
242  *******************************************************************/
243 ASM_ENTRY(romfs_lookup)
244         mflr    r9
245         
246   romfs_lookup_next:
247         /* save current file base        */
248         mr      r8, r4
249         /* name to look for              */
250         mr      r10, r3 
251         /* name of file                  */
252         mr      r5,  r4
253         addi    r5,  r5, (4 /* elems     */ * 8 /* elem-size */)
254         mr      r11, r5 /* for namematch */
255         /* compare                       */
256         bl      romfs_namematch
257         cmpwi   r12, 1
258         bne     romfs_lookup_match
259
260         /* load next pointer             */
261         /* check if next is 0            */
262         /* apply root-offset             */
263         ld      r5, 0(r4)
264         cmpwi   r5, 0
265         add     r4, r4, r5
266         bne     romfs_lookup_next
267         /* last file reached, abort      */
268         li      r3, 1
269         mtlr    r9
270         blr
271
272         /* here the name did match       */
273         /* r4 is still usable here and   */
274         /* pointing to the initial file  */
275         /* load r5 with data ptr         */
276         /* load r6 with data size        */
277         /* load r7 with flags            */
278         /* get abs addr of data          */
279   romfs_lookup_match:
280         li      r3, 0
281         ld      r5, (3 * 8)(r4) /* data  */
282         ld      r6, (1 * 8)(r4) /* len   */
283         ld      r7, (2 * 8)(r4) /* flags */
284         add     r5, r5, r8
285         mtlr    r9
286         blr
287
288 /*******************************************************************
289  * compares two strings in memory, 
290  * both must be null-terminated and 8-byte aligned
291  *
292  * Input:
293  * R10 = string 1
294  * R11 = string 2
295  *
296  * Returns:
297  * <Match>: R12 = 0 <NoMatch>: R12 = 1
298  *
299  * Potentially modifies the following registers:
300  * R10, R11, r12, r13, r14 
301  *******************************************************************/
302 romfs_namematch:
303         subi    r10, r10, 8
304         subi    r11, r11, 8
305
306         /* 
307          * load chars as 8byte chunk from current pos, name is 
308          * always 8 byte aligned :)
309          */
310   romfs_cmp_loop:
311         ldu     r13, 8(r10) /* A */
312         ldu     r14, 8(r11) /* B */
313
314         cmpd    r13, r14
315         li      r12, 1
316         beq     1f
317         blr
318
319 1:      andi.   r14, r14, 0xff
320         bne     romfs_cmp_loop
321
322         li      r12, 0
323         blr
324
325 /*******************************************************************
326  * wrapper for romfs_lookup
327  * this function saves the registers from r13 - r15 on the stack
328  * calls romfs_lookup
329  * restores the saved registers
330  *
331  * the return parameters are copied to (r5) and (r5) has to
332  * be 0x20 big
333  *******************************************************************/
334 ENTRY(c_romfs_lookup)
335         stdu    r1,-0x50(r1)            # allocate space on stack
336
337         mflr    r0                      # save link register
338         std     r0,0x30(r1)
339
340         std     r15,0x38(r1)            # save r15
341         std     r14,0x40(r1)            # save r14
342         std     r13,0x48(r1)            # and r13
343         
344         mr      r15,r5                  # save the pointer for the return value
345
346         bl      romfs_lookup            # do the thing
347
348         ld      r0,0x30(r1)             # restore link register
349         mtlr    r0
350
351         std     r4,0x00(r15)            # copy return values
352         std     r5,0x08(r15)            # to the return pointer
353         std     r6,0x10(r15)
354         std     r7,0x18(r15)
355
356         ld      r13,0x48(r1)            # restore registers from stack
357         ld      r14,0x40(r1)
358         ld      r15,0x38(r1)
359
360         addi    r1,r1,0x50              # cleanup stack
361
362         blr