/****************************************************************************** * Copyright (c) 2004, 2008 IBM Corporation * All rights reserved. * This program and the accompanying materials * are made available under the terms of the BSD License * which accompanies this distribution, and is available at * http://www.opensource.org/licenses/bsd-license.php * * Contributors: * IBM Corporation - initial implementation *****************************************************************************/ #include "macros.h" #include "romfs.h" /******************************************************************* * Wrapper for romfs_lookup. * * Input: * R3 = address of filename string * R4 = address of struct romfs_t * 0: file size (return) * 8: flags (return) * 10: fileaddr (return and input: tells if first search) * 18: nextfile (return) * 20: namep (return) * * Find File Procedure * - set filename and rombase, on return 0 file properties are stored * in romfs_t else struct not valid * * Listing procedure * - clear romfs_t (important!) * - set filename = NULL and rombase and call returns first file * with properties in romfs_t including next-file pointer * - if nextpointer is non-zero then just the next file is returned * * Returns: * : * R3 = 0 * romfs_t is updated * : * R3 = 1 * romfs_t not touched * * Potentially modifies the following registers: * Example usage from C: int list_bootrom() { struct romfs_t rfs; int i; printf("Build: "__TIME__" "__DATE__" \n"); i = 0; memset((void*) &rfs, 0, sizeof(struct romfs_t)); printf(" No. File Data Size Name\n"); while (romfs_stat(NULL, &rfs) == 0) { i++; printf(" %02d: %08X %08X %7d %s\n", i, rfs.fileaddr, rfs.datap, rfs.size, rfs.namep); } if (0 == i) { printf("Error in reading ROMFS\n"); return 1; } return 0; } *******************************************************************/ #define RFS_T_SIZE 0x00 #define RFS_T_FLAGS 0x08 #define RFS_T_FILEADDR 0x10 #define RFS_T_NEXT 0x18 #define RFS_T_NAME 0x20 #define RFS_T_DATA 0x28 #define RFS_H_NEXT 0x00 #define RFS_H_SIZE 0x08 #define RFS_H_FLAGS 0x10 #define RFS_H_DATA 0x18 #define RFS_H_NAME 0x20 ENTRY(romfs_stat_file) /* save link register and romfs_t pointer */ mflr r15 mr r16, r4 /* if filename R3 is 0 then its a listing request */ /* if not then just continue to lookup name */ /* save R4 to R8 which is the address of header */ li r7, 0 cmpd r3, r7 beq romfs_list bl romfs_lookup mfsprg r8, 1 /* if file found then go to romfs_fill_properties */ /* else return 1 to caller */ cmpwi r3, 0 beq romfs_fill_properties b romfs_stat_end romfs_list: /* check if fileaddr == 0, in this case its */ /* the first search on this handle, so return all */ /* info for file at rombase (R8=R4) */ ld r6, RFS_T_FILEADDR(r4) mfsprg r8, 1 li r7, 0 cmpd r7, r6 beq romfs_fill_properties /* check if next file != 0 by looking into */ /* romfs_t, if not then return (next = 0) 1 */ li r7, 0 ld r4, RFS_T_NEXT(r4) cmpd r7, r4 li r3, 1 beq romfs_stat_end /* now next file is available so move R8 to next */ /* file address */ mr r8, r4 romfs_fill_properties: /* set properties in romfs_t takes R8 as address */ /* to file header and R16 as address of romfs_t */ mfsprg r3, 1 std r8, RFS_T_FILEADDR(r16) ld r4, RFS_H_NEXT(r8) li r7, 0 cmpd r7, r4 beq $ + (2 * 4) /* =0 so add no rombase */ add r4, r4, r3 std r4, RFS_T_NEXT(r16) ld r4, RFS_H_SIZE(r8) std r4, RFS_T_SIZE(r16) ld r4, RFS_H_FLAGS(r8) std r4, RFS_T_FLAGS(r16) ld r4, RFS_H_DATA(r8) add r4, r4, r3 std r4, RFS_T_DATA(r16) addi r4, r8, RFS_H_NAME std r4, RFS_T_NAME(r16) li r3, 0 /* restore romfs_t pointer and link register */ romfs_stat_end: mr r5, r16 mtlr r15 blr /******************************************************************* * Copies the data of file referenced by name string to address * requires root address of filesystem. * FIXME: ignores flags * * Input: * R3 = address of filename string * R4 = ROMBASE * R5 = destination address * * Returns: * : R3 = 0, R6 = size, : R3 = 1 * R5 is kept * * Potentially modifies the following registers: * ctr, r15, r16, r17, r18 * * Uses the following calls with subsequent register modification: * - romfs_lookup *******************************************************************/ ASM_ENTRY(romfs_load) mflr r15 /* save R5 twice */ /* lookup file, input regs */ /* are already set */ /* if not found, just return */ mr r16, r5 mr r17, r5 bl romfs_lookup cmpwi r3, 1 bne 0f mtlr r15 blr /* abort, not found */ /* save data size for return */ /* found, copy data */ /* data size is in R6 */ 0: //mr r3, r6 mtctr r6 addi r16, r16, -1 /* dest */ addi r5, r5, -1 /* source*/ /* data is expected to be */ /* 8 byte aligned */ /* copy loop */ 0: lbzu r18, 1(r5) stbu r18, 1(r16) bdnz 0b /* restore size, keep padding */ /* restore target address */ /* return */ mr r5, r17 mtlr r15 blr /******************************************************************* * looks up a file based on filename * * Input: * R3 = address of filename string * R4 = ROMBASE * * Returns: * : * R3 = 0 * R4 = address of file header * R5 = address of data (real address) * R6 = size of data * R7 = flags for file * : * R3 = 1 * * Potentially modifies the following registers: * R3, R4, R5, R6, R7, R8, R9 * * Uses the following calls with subsequent register modification: * - romfs_namematch *******************************************************************/ ASM_ENTRY(romfs_lookup) mflr r9 romfs_lookup_next: /* save current file base */ mr r8, r4 /* name to look for */ mr r10, r3 /* name of file */ mr r5, r4 addi r5, r5, (4 /* elems */ * 8 /* elem-size */) mr r11, r5 /* for namematch */ /* compare */ bl romfs_namematch cmpwi r12, 1 bne romfs_lookup_match /* load next pointer */ /* check if next is 0 */ /* apply root-offset */ ld r5, 0(r4) cmpwi r5, 0 add r4, r4, r5 bne romfs_lookup_next /* last file reached, abort */ li r3, 1 mtlr r9 blr /* here the name did match */ /* r4 is still usable here and */ /* pointing to the initial file */ /* load r5 with data ptr */ /* load r6 with data size */ /* load r7 with flags */ /* get abs addr of data */ romfs_lookup_match: li r3, 0 ld r5, (3 * 8)(r4) /* data */ ld r6, (1 * 8)(r4) /* len */ ld r7, (2 * 8)(r4) /* flags */ add r5, r5, r8 mtlr r9 blr /******************************************************************* * compares two strings in memory, * both must be null-terminated and 8-byte aligned * * Input: * R10 = string 1 * R11 = string 2 * * Returns: * : R12 = 0 : R12 = 1 * * Potentially modifies the following registers: * R10, R11, r12, r13, r14 *******************************************************************/ romfs_namematch: subi r10, r10, 8 subi r11, r11, 8 /* * load chars as 8byte chunk from current pos, name is * always 8 byte aligned :) */ romfs_cmp_loop: ldu r13, 8(r10) /* A */ ldu r14, 8(r11) /* B */ cmpd r13, r14 li r12, 1 beq 1f blr 1: andi. r14, r14, 0xff bne romfs_cmp_loop li r12, 0 blr /******************************************************************* * wrapper for romfs_lookup * this function saves the registers from r13 - r15 on the stack * calls romfs_lookup * restores the saved registers * * the return parameters are copied to (r5) and (r5) has to * be 0x20 big *******************************************************************/ ENTRY(c_romfs_lookup) stdu r1,-0x50(r1) # allocate space on stack mflr r0 # save link register std r0,0x30(r1) std r15,0x38(r1) # save r15 std r14,0x40(r1) # save r14 std r13,0x48(r1) # and r13 mr r15,r5 # save the pointer for the return value bl romfs_lookup # do the thing ld r0,0x30(r1) # restore link register mtlr r0 std r4,0x00(r15) # copy return values std r5,0x08(r15) # to the return pointer std r6,0x10(r15) std r7,0x18(r15) ld r13,0x48(r1) # restore registers from stack ld r14,0x40(r1) ld r15,0x38(r1) addi r1,r1,0x50 # cleanup stack blr