blob: 3ad2de75440812a32682c6f8e1ecabe1ce771736 [file] [log] [blame]
/******************************************************************************
* 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