1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
4 * This program and the accompanying materials
5 * are made available under the terms of the BSD License
6 * which accompanies this distribution, and is available at
7 * http://www.opensource.org/licenses/bsd-license.php
10 * IBM Corporation - initial implementation
11 *****************************************************************************/
14 #include <southbridge.h>
15 #include <calculatecrc.h>
17 #if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
19 // detect overflow: if(a<b) return a else return 0
20 #define NVRAM_LOG_DATA_OVERFLOW( a, b) \
26 // get Pointer(pointer) to next byte in NVRAM data section
27 // and size of this data sechtion (modulo)
28 // modifies register pointer, modulo
29 #define NVRAM_POINTER_DATASIZE_BE0(pointer, modulo, address) \
30 LOAD64( modulo, LLFW_LOG_BE0_LENGTH); \
31 lwz pointer, LLFW_LOG_POS_POINTER(address); \
32 sldi modulo, modulo, 4; \
33 addi modulo, modulo,-LLFW_LOG_BE0_DATA_OFFSET
34 #define NVRAM_POINTER_DATASIZE_BE1(pointer, modulo, address) \
35 LOAD64( modulo, LLFW_LOG_BE1_LENGTH); \
36 lwz pointer, LLFW_LOG_POS_POINTER(address); \
37 sldi modulo, modulo, 4; \
38 addi modulo, modulo,-LLFW_LOG_BE1_DATA_OFFSET
40 /****************************************************************************
42 * compare the fixed values in the header if any change was done since
43 * last initialisation.
44 * Flags are not checked!
46 * Retrun 0 if no manimulation was found 1 else
49 * r3 - NVRAM Base Address
52 * r3 - status: 0 = ok, 1 = corrupt
53 * r4 - NVRAM Base Address
55 ***************************************************************************/
56 ASM_ENTRY(checkLogHeaderData)
57 li r4, 0 // init error flag
58 lbz r5, 0(r3) // check signature
59 addi r5, r5, -LLFW_LOG_BE0_SIGNATURE
62 lhz r5, LLFW_LOG_POS_LENGTH(r3) // check length
63 addi r5, r5, -LLFW_LOG_BE0_LENGTH
66 lwz r5, LLFW_LOG_POS_NAME(r3) // check name prefix
67 LOAD64( r6, LLFW_LOG_BE0_NAME_PREFIX)
71 ld r5, (LLFW_LOG_POS_NAME+4)(r3) // check name
72 LOAD64( r6, LLFW_LOG_BE0_NAME)
76 lhz r5, LLFW_LOG_POS_DATA_OFFSET(r3) //check data offset
77 addi r5, r5, -LLFW_LOG_BE0_DATA_OFFSET
80 lhz r5, LLFW_LOG_POS_FLAGS(r3) //check flags
81 addi r5, r5, -LLFW_LOG_BE0_FLAGS
92 /*****************************************************************************
93 * checkLogPartition: check Partition Header entries and Checksum
94 * check also the NVRAM-Log-Partition CRC
95 * if Partition is not ok set the following bits to 1
96 * bit 1: if Partiton Header Checksum is corrupt
97 * bit 2: if CRC is corrupt
98 * bit 3: if Header entries are corrupt
101 * r3 - NVRAM log address (BASE + NVRAM_LOG_OFFSET)
105 * r4 - NVRAM log address
107 * Modifies Register: R3, R4, R5, R6, R7, R8, R9
108 ****************************************************************************/
109 ASM_ENTRY(.checkLogPartition)
111 mr r4, r3 // emulate "bl updateCRC_NVRAM"
112 li r3, 0 // with successful CRC check
119 bl .calPartitionHeaderChecksum // r3=checksum, r4=NVARM addr
120 lbz r6, LLFW_LOG_POS_CHECKSUM(r4)
122 beq+ 7, 0f // cal checksum must eq checksum
127 ori r7, r7, 1 // 0 as checksum is invalid
130 bl checkLogHeaderData
138 /*****************************************************************************
139 * checkinitLog: check the NVRAM Log Partition Header
140 * initialize the NVRAM if the Header was modified
143 * r3 - NVRAM BASE address
146 * r3 - 0 = check ok, no new header written
147 * r3 - 1 = check not ok, header and NVRAM initialized
148 * r4 - NVRAM log address
150 * Modifies Register: R3, R4, R5, R6, R7, r8, r9
151 ****************************************************************************/
152 // init is done if checkLogPartiton returns not 0 (= check failed)
153 ASM_ENTRY(.checkinitLog)
154 ASM_ENTRY(checkinitLog)
156 bl .checkLogPartition //r3..r8, r4_out = r3_in
160 mr r3, r4 // r3=NVRAM_LOG address
161 bne- 7, .initLog // if header is not ok, init header
163 blr // header OK, return 0
166 /* this is basically just a copy of .initLog
167 registers used: r3, r4, r5, r6, r7, r9*/
170 li r6, LLFW_LOG_BE0_LENGTH
173 li r5, LLFW_LOG_BE1_SIGNATURE
174 li r4, LLFW_LOG_BE1_LENGTH
176 sth r4, LLFW_LOG_POS_LENGTH(r6)
177 li r5, LLFW_LOG_BE1_DATA_OFFSET
178 li r4, LLFW_LOG_BE1_FLAGS
179 sth r5, LLFW_LOG_POS_DATA_OFFSET(r6)
180 sth r4, LLFW_LOG_POS_FLAGS(r6)
183 LOAD32( r4, LLFW_LOG_BE1_NAME_PREFIX)
184 stw r5, LLFW_LOG_POS_POINTER(r6)
185 stw r4, (LLFW_LOG_POS_NAME+0x00)(r6)
186 LOAD64( r5, LLFW_LOG_BE1_NAME)
187 std r5, (LLFW_LOG_POS_NAME+0x04)(r6)
189 bl .calPartitionHeaderChecksum
190 stb r3, LLFW_LOG_POS_CHECKSUM(r6)
193 /*****************************************************************************
194 * initLog: initialize the NVRAM with 0
195 * write a new NVRAM Log-Partition-Header
198 * r3 - NVRAM BASE address
201 * r3 - 0 = check ok, no new header written
202 * r3 - 1 = check not ok, header and NVRAM initialized
203 * r4 - NVRAM log address
205 * Modifies Register: R3, R4, R5, R6, R7, r8, r9
206 ****************************************************************************/
213 li r5, LLFW_LOG_BE0_SIGNATURE
214 li r4, LLFW_LOG_BE0_LENGTH
216 sth r4, LLFW_LOG_POS_LENGTH(r7)
217 li r5, LLFW_LOG_BE0_DATA_OFFSET
218 li r4, LLFW_LOG_BE0_FLAGS
219 sth r5, LLFW_LOG_POS_DATA_OFFSET(r7)
220 sth r4, LLFW_LOG_POS_FLAGS(r7)
223 LOAD32( r4, LLFW_LOG_BE0_NAME_PREFIX)
224 stw r5, LLFW_LOG_POS_POINTER(r7)
225 stw r4, (LLFW_LOG_POS_NAME+0x00)(r7)
226 LOAD64( r5, LLFW_LOG_BE0_NAME)
227 std r5, (LLFW_LOG_POS_NAME+0x04)(r7)
228 bl .calPartitionHeaderChecksum
229 stb r3, LLFW_LOG_POS_CHECKSUM(r7)
230 bl init_log_2nd_be // create a second log partition for BE1
235 /*****************************************************************************
236 * clearNVRAM: set all not used NVRAM memory to zero
240 * R3 - NVRAM BASE ADDRESS
243 * R3 - NVARM END ADDRESS
245 * Modifies Register: r4, r5
246 ****************************************************************************/
247 ASM_ENTRY(clearNVRAM)
248 LOAD64( r4, NVRAM_LENGTH)
252 LOAD64( r4, NVRAM_EMPTY_PATTERN)
258 /*****************************************************************************
259 * writeNVRAMbyte: write next log into NVRAM
263 * R3 - byte to be written
264 * R4 - NVRAM Base Address
267 * R3 - byte that was written
268 * R4 - NVRAM Base Address
270 * Modifies Register: R3, R4, R5, R6
271 ****************************************************************************/
272 ASM_ENTRY(.writeNVRAMbyte)
274 NVRAM_POINTER_DATASIZE_BE0( r5, r6, r4) // get pointer,size of data
275 NVRAM_LOG_DATA_OVERFLOW( r5, r6) // check for overflow
276 addi r5, r5, 1 // increment pointer
277 stw r5, LLFW_LOG_POS_POINTER(r4) // store pointer
278 addi r5, r5, -1 // restore old pointer
279 add r6, r4, r5 // byte address in data section
281 stb r3, LLFW_LOG_BE0_DATA_OFFSET(r6)
284 /*****************************************************************************
285 * writeNVRAMbyte: write next log into NVRAM
289 * R3 - byte to be written
290 * R4 - NVRAM Base Address
293 * R3 - byte that was written
294 * R4 - NVRAM Base Address
296 * Modifies Register: R3, R4, R5, R6
297 ****************************************************************************/
298 ENTRY(writeLogByteBE1)
299 li r6, LLFW_LOG_BE0_LENGTH
302 NVRAM_POINTER_DATASIZE_BE1( r5, r6, r4) // get pointer,size of data
303 NVRAM_LOG_DATA_OVERFLOW( r5, r6) // check for overflow
304 addi r5, r5, 1 // increment pointer
305 stw r5, LLFW_LOG_POS_POINTER(r4) // store pointer
306 addi r5, r5, -1 // restore old pointer
307 add r6, r4, r5 // byte address in data section
309 stb r3, LLFW_LOG_BE1_DATA_OFFSET(r6)
312 /*****************************************************************************
313 * calPartitionHeaderChecksum: calculate the Checksum of the
314 * Partition Header as described in ....
316 * input: r3 - NVRAM BASE adresse
318 * output: R3 - the calculated checksum as 8 bit value
319 * R4 - NVRAM log address
321 * Modifies Register: R3, R4, R5, R6
322 ****************************************************************************/
323 ASM_ENTRY(.calPartitionHeaderChecksum)
325 lbz r3,0(r6) // load first byte
326 LOAD64( r4, LLFW_LOG_POS_LENGTH) // load position of 3rd byte
328 lbzx r5, r4, r6 // r5 nexed byte
329 addi r4, r4, 1 // r4++ (index)
330 add r5, r5, r3 // r5 new sum =sum + nexed byte
333 cmpldi 6, r4, LLFW_LOG_POS_DATA_OFFSET
334 bge+ 7,.L5 // if new sum > sum
335 addi r5, r5, 1 // new sum ++
338 mr r3,r5 // sum = new sum
344 #else /* defined(DISABLE_NVRAM) || defined(RTAS_NVRAM) */
346 ASM_ENTRY(.writeNVRAMbyte)