summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/llfw/romfs.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/llfw/romfs.S')
-rw-r--r--qemu/roms/SLOF/llfw/romfs.S362
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