Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / llfw / romfs.S
diff --git a/qemu/roms/SLOF/llfw/romfs.S b/qemu/roms/SLOF/llfw/romfs.S
new file mode 100644 (file)
index 0000000..325f79e
--- /dev/null
@@ -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