Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / llfw / nvramlog.S
diff --git a/qemu/roms/SLOF/llfw/nvramlog.S b/qemu/roms/SLOF/llfw/nvramlog.S
new file mode 100644 (file)
index 0000000..3ad2de7
--- /dev/null
@@ -0,0 +1,350 @@
+/******************************************************************************
+ * 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 <nvramlog.h>
+#include <southbridge.h>
+#include <calculatecrc.h>
+
+#if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
+
+// detect overflow: if(a<b)  return a else return 0
+#define NVRAM_LOG_DATA_OVERFLOW( a, b) \
+       cmpd    7, a, b; \
+       blt+    7, 0f; \
+       li      a, 0; \
+       0:
+
+// get Pointer(pointer) to next byte in NVRAM data section
+//  and size of this data sechtion (modulo)
+// modifies register pointer, modulo
+#define NVRAM_POINTER_DATASIZE_BE0(pointer, modulo, address) \
+       LOAD64( modulo, LLFW_LOG_BE0_LENGTH); \
+       lwz     pointer, LLFW_LOG_POS_POINTER(address); \
+       sldi    modulo, modulo, 4; \
+       addi    modulo, modulo,-LLFW_LOG_BE0_DATA_OFFSET
+#define NVRAM_POINTER_DATASIZE_BE1(pointer, modulo, address) \
+       LOAD64( modulo, LLFW_LOG_BE1_LENGTH); \
+       lwz     pointer, LLFW_LOG_POS_POINTER(address); \
+       sldi    modulo, modulo, 4; \
+       addi    modulo, modulo,-LLFW_LOG_BE1_DATA_OFFSET
+
+/****************************************************************************
+ *     checkLogHeaderData
+ *     compare the fixed values in the header if any change was done since
+ *     last initialisation.
+ *     Flags are not checked!
+ *
+ *     Retrun 0 if no manimulation was found 1 else
+ *
+ *     input:
+ *                     r3 - NVRAM Base Address 
+ *
+ *     output:
+ *                     r3 - status: 0 = ok, 1 = corrupt
+ *                     r4 - NVRAM Base Address
+ *
+ ***************************************************************************/
+ASM_ENTRY(checkLogHeaderData)
+       li      r4, 0                                   // init error flag
+       lbz     r5, 0(r3)                               // check signature
+       addi    r5, r5, -LLFW_LOG_BE0_SIGNATURE
+       add     r4, r4, r5
+
+       lhz     r5, LLFW_LOG_POS_LENGTH(r3)             // check length
+       addi    r5, r5, -LLFW_LOG_BE0_LENGTH
+       add     r4, r4, r5
+
+       lwz     r5, LLFW_LOG_POS_NAME(r3)               // check name prefix
+       LOAD64( r6, LLFW_LOG_BE0_NAME_PREFIX)
+       subf    r5, r6, r5
+       add     r4, r4, r5
+
+       ld      r5, (LLFW_LOG_POS_NAME+4)(r3)           // check name
+       LOAD64( r6, LLFW_LOG_BE0_NAME)
+       subf    r5, r6, r5
+       add     r4, r4, r5
+       
+       lhz     r5, LLFW_LOG_POS_DATA_OFFSET(r3)        //check data offset
+       addi    r5, r5, -LLFW_LOG_BE0_DATA_OFFSET
+       add     r4, r4, r5
+
+       lhz     r5, LLFW_LOG_POS_FLAGS(r3)              //check flags
+       addi    r5, r5, -LLFW_LOG_BE0_FLAGS
+       add     r4, r4, r5
+
+       cmpldi  7, r4, 0
+       beq+    7, 0f
+       li      r4, 1
+0:
+       mr      r5, r3
+       mr      r3, r4
+       mr      r4, r5
+       blr
+/*****************************************************************************
+ * checkLogPartition:  check Partition Header entries and Checksum
+ *                     check also the NVRAM-Log-Partition CRC
+ *                     if Partition is not ok set the following bits to 1
+ *                     bit 1:  if Partiton Header Checksum is corrupt
+ *                     bit 2:  if CRC is corrupt
+ *                     bit 3:  if Header entries are corrupt
+ *                                             
+ *     input:  
+ *             r3 - NVRAM log address (BASE + NVRAM_LOG_OFFSET)
+ *
+ *     output: 
+ *             r3 - CRC status  
+ *             r4 - NVRAM log address
+ *
+ *     Modifies Register:      R3, R4, R5, R6, R7, R8, R9
+ ****************************************************************************/
+ASM_ENTRY(.checkLogPartition)
+       mflr    r8
+       mr      r4, r3                  // emulate "bl updateCRC_NVRAM"
+       li      r3, 0                   // with successful CRC check
+       li      r7, 0
+       cmpwi   7, r3, 0
+       beq+    7, 0f
+       li      r7, 2
+0:
+       mr      r3, r4
+       bl      .calPartitionHeaderChecksum     // r3=checksum, r4=NVARM addr
+       lbz     r6, LLFW_LOG_POS_CHECKSUM(r4)
+       cmpw    7, r3, r6
+       beq+    7, 0f                   // cal checksum must eq checksum
+       ori     r7, r7, 1
+0:
+       cmpwi   7, r3, 0
+       bne+    7, 0f
+       ori     r7, r7, 1               // 0 as checksum is invalid
+0:
+       mr      r3, r4
+       bl      checkLogHeaderData      
+       cmpdi   7, r3, 0
+       beq+    7, 0f
+       ori     r7, r7, 4
+0:
+       mr      r3, r7
+       mtlr    r8
+       blr
+/*****************************************************************************
+ * checkinitLog:       check the NVRAM Log Partition Header 
+ *                     initialize the NVRAM if the Header was modified
+ *                                     
+ *     input:  
+ *             r3 - NVRAM BASE address 
+ *
+ *     output: 
+ *             r3 - 0 = check ok, no new header written
+ *             r3 - 1 = check not ok, header and NVRAM initialized
+ *             r4 - NVRAM log address
+ *
+ *     Modifies Register:      R3, R4, R5, R6, R7, r8, r9
+ ****************************************************************************/
+// init is done if checkLogPartiton returns not 0 (= check failed)
+ASM_ENTRY(.checkinitLog)
+ASM_ENTRY(checkinitLog)
+       mflr    r9
+       bl      .checkLogPartition              //r3..r8, r4_out = r3_in   
+       mtlr    r9
+       
+       cmpwi   7, r3, 0
+       mr      r3, r4                  // r3=NVRAM_LOG address
+       bne-    7, .initLog             // if header is not ok, init header
+       li      r3, 0
+       blr                             // header OK, return 0                  
+
+
+/* this is basically just a copy of .initLog 
+   registers used: r3, r4, r5, r6, r7, r9*/
+init_log_2nd_be:
+       mflr    r9      
+       li      r6, LLFW_LOG_BE0_LENGTH
+       mulli   r6, r6, 0x10
+       add     r6, r7, r6
+       li      r5, LLFW_LOG_BE1_SIGNATURE
+       li      r4, LLFW_LOG_BE1_LENGTH
+       stb     r5, 0(r6)
+       sth     r4, LLFW_LOG_POS_LENGTH(r6)
+       li      r5, LLFW_LOG_BE1_DATA_OFFSET
+       li      r4, LLFW_LOG_BE1_FLAGS
+       sth     r5, LLFW_LOG_POS_DATA_OFFSET(r6)
+       sth     r4, LLFW_LOG_POS_FLAGS(r6)
+       li      r5, 1
+
+       LOAD32( r4, LLFW_LOG_BE1_NAME_PREFIX)
+       stw     r5, LLFW_LOG_POS_POINTER(r6)
+       stw     r4, (LLFW_LOG_POS_NAME+0x00)(r6)
+       LOAD64( r5, LLFW_LOG_BE1_NAME)
+       std     r5, (LLFW_LOG_POS_NAME+0x04)(r6)
+       mr      r3, r6
+       bl      .calPartitionHeaderChecksum
+       stb     r3, LLFW_LOG_POS_CHECKSUM(r6)
+       mtlr    r9
+       blr
+/*****************************************************************************
+ * initLog:    initialize the NVRAM with 0
+ *             write a new NVRAM Log-Partition-Header
+ *                                     
+ *     input:  
+ *             r3 - NVRAM BASE address 
+ *
+ *     output: 
+ *             r3 - 0 = check ok, no new header written
+ *             r3 - 1 = check not ok, header and NVRAM initialized
+ *             r4 - NVRAM log address
+ *
+ *     Modifies Register:      R3, R4, R5, R6, R7, r8, r9
+ ****************************************************************************/
+ASM_ENTRY(.initLog)
+       mflr    r8
+       mr      r7, r3
+
+       bl clearNVRAM
+0:
+       li      r5, LLFW_LOG_BE0_SIGNATURE
+       li      r4, LLFW_LOG_BE0_LENGTH
+       stb     r5, 0(r7)
+       sth     r4, LLFW_LOG_POS_LENGTH(r7)
+       li      r5, LLFW_LOG_BE0_DATA_OFFSET
+       li      r4, LLFW_LOG_BE0_FLAGS
+       sth     r5, LLFW_LOG_POS_DATA_OFFSET(r7)
+       sth     r4, LLFW_LOG_POS_FLAGS(r7)
+       li      r5, 1
+
+       LOAD32( r4, LLFW_LOG_BE0_NAME_PREFIX)
+       stw     r5, LLFW_LOG_POS_POINTER(r7)
+       stw     r4, (LLFW_LOG_POS_NAME+0x00)(r7)
+       LOAD64( r5, LLFW_LOG_BE0_NAME)
+       std     r5, (LLFW_LOG_POS_NAME+0x04)(r7)
+       bl      .calPartitionHeaderChecksum
+       stb     r3, LLFW_LOG_POS_CHECKSUM(r7)
+       bl      init_log_2nd_be                 // create a second log partition for BE1
+       mr      r4, r7
+       li      r3, 1
+       mtlr    r8
+       blr
+/*****************************************************************************
+ *     clearNVRAM:     set all not used NVRAM memory to zero
+ *
+ *
+ *     input:  
+ *             R3 - NVRAM BASE ADDRESS
+ *
+ *     output: 
+ *             R3 - NVARM END ADDRESS
+ *
+ *     Modifies Register: r4, r5
+ ****************************************************************************/
+ASM_ENTRY(clearNVRAM)
+       LOAD64( r4, NVRAM_LENGTH)
+       srdi    r4, r4, 3
+       mtctr   r4
+       li      r5, 0x0
+       LOAD64( r4, NVRAM_EMPTY_PATTERN)
+0:
+       stdx    r4, r3,r5
+       addi    r5, r5, 8
+       bdnz+   0b
+       blr     
+/*****************************************************************************
+ * writeNVRAMbyte:     write next log into NVRAM
+ *                                     
+ *
+ *     input:  
+ *             R3 - byte to be written
+ *             R4 - NVRAM Base Address
+ *
+ *     output: 
+ *             R3 - byte that was written
+ *             R4 - NVRAM Base Address 
+ *
+ *     Modifies Register:      R3, R4, R5, R6
+ ****************************************************************************/
+ASM_ENTRY(.writeNVRAMbyte)
+ENTRY(writeLogByte)
+       NVRAM_POINTER_DATASIZE_BE0( r5, r6, r4) // get pointer,size of data
+       NVRAM_LOG_DATA_OVERFLOW( r5, r6)        // check for overflow
+       addi    r5, r5, 1                       // increment pointer
+       stw     r5, LLFW_LOG_POS_POINTER(r4)    // store pointer
+       addi    r5, r5, -1                      // restore old pointer
+       add     r6, r4, r5                      // byte address in data section 
+
+       stb     r3, LLFW_LOG_BE0_DATA_OFFSET(r6)        
+       blr
+
+/*****************************************************************************
+ * writeNVRAMbyte:     write next log into NVRAM
+ *                                     
+ *
+ *     input:  
+ *             R3 - byte to be written
+ *             R4 - NVRAM Base Address
+ *
+ *     output: 
+ *             R3 - byte that was written
+ *             R4 - NVRAM Base Address 
+ *
+ *     Modifies Register:      R3, R4, R5, R6
+ ****************************************************************************/
+ENTRY(writeLogByteBE1)
+       li      r6, LLFW_LOG_BE0_LENGTH
+       mulli   r6, r6, 0x10
+       add     r4, r6, r4
+       NVRAM_POINTER_DATASIZE_BE1( r5, r6, r4) // get pointer,size of data
+       NVRAM_LOG_DATA_OVERFLOW( r5, r6)        // check for overflow
+       addi    r5, r5, 1                       // increment pointer
+       stw     r5, LLFW_LOG_POS_POINTER(r4)    // store pointer
+       addi    r5, r5, -1                      // restore old pointer
+       add     r6, r4, r5                      // byte address in data section 
+
+       stb     r3, LLFW_LOG_BE1_DATA_OFFSET(r6)        
+       blr
+
+/*****************************************************************************
+ * calPartitionHeaderChecksum:         calculate the Checksum of the 
+ *     Partition Header as described in ....
+ *
+ *     input: r3 - NVRAM BASE adresse
+ *
+ *     output: R3 - the calculated checksum as 8 bit value 
+ *                     R4 - NVRAM log address
+ *
+ *     Modifies Register:      R3, R4, R5, R6
+ ****************************************************************************/
+ASM_ENTRY(.calPartitionHeaderChecksum)
+       mr      r6, r3
+       lbz     r3,0(r6)                        // load first byte
+       LOAD64( r4, LLFW_LOG_POS_LENGTH)        // load position of 3rd byte
+.L6:
+       lbzx    r5, r4, r6                      // r5  nexed byte
+       addi    r4, r4, 1                       // r4++ (index)
+       add     r5, r5, r3                      // r5 new sum =sum +  nexed byte
+       rldicl  r5, r5, 0, 56
+       cmpld   7, r5, r3                                       
+       cmpldi  6, r4, LLFW_LOG_POS_DATA_OFFSET
+       bge+    7,.L5                           // if new sum > sum 
+       addi    r5, r5, 1                       // new sum ++
+       rldicl  r5, r5, 0, 56
+.L5:
+       mr      r3,r5                           // sum = new sum
+       blt+    6,.L6
+
+       mr r4, r6
+       blr
+
+#else  /* defined(DISABLE_NVRAM) || defined(RTAS_NVRAM) */
+
+ASM_ENTRY(.writeNVRAMbyte)
+       ENTRY(writeLogByte)
+       blr
+
+#endif