349 lines
9.8 KiB
ArmAsm
349 lines
9.8 KiB
ArmAsm
/******************************************************************************
|
|
* 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>
|
|
|
|
#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
|