diff options
Diffstat (limited to 'roms/SLOF/llfw/nvramlog.S')
-rw-r--r-- | roms/SLOF/llfw/nvramlog.S | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/roms/SLOF/llfw/nvramlog.S b/roms/SLOF/llfw/nvramlog.S new file mode 100644 index 000000000..be6bfd871 --- /dev/null +++ b/roms/SLOF/llfw/nvramlog.S @@ -0,0 +1,351 @@ +/****************************************************************************** + * 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) + +// 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 successfull 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) */ + +ASM_ENTRY(.writeNVRAMbyte) + ENTRY(writeLogByte) + blr + +#endif |