summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/llfw/nvramlog.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/SLOF/llfw/nvramlog.S')
-rw-r--r--qemu/roms/SLOF/llfw/nvramlog.S350
1 files changed, 350 insertions, 0 deletions
diff --git a/qemu/roms/SLOF/llfw/nvramlog.S b/qemu/roms/SLOF/llfw/nvramlog.S
new file mode 100644
index 000000000..3ad2de754
--- /dev/null
+++ b/qemu/roms/SLOF/llfw/nvramlog.S
@@ -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