diff options
Diffstat (limited to 'qemu/roms/SLOF/llfw/romfs.S')
-rw-r--r-- | qemu/roms/SLOF/llfw/romfs.S | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/llfw/romfs.S b/qemu/roms/SLOF/llfw/romfs.S new file mode 100644 index 000000000..325f79e5e --- /dev/null +++ b/qemu/roms/SLOF/llfw/romfs.S @@ -0,0 +1,362 @@ +/****************************************************************************** + * 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: + * <Success>: + * R3 = 0 + * romfs_t is updated + * <FileNotFound>: + * 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: + * <Success>: R3 = 0, R6 = size, <FileNotFound>: 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: + * <Success>: + * R3 = 0 + * R4 = address of file header + * R5 = address of data (real address) + * R6 = size of data + * R7 = flags for file + * <FileNotFound>: + * 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: + * <Match>: R12 = 0 <NoMatch>: 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 |