1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
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
|