Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / llfw / nvramlog.S
1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
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
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 #include <macros.h>
13 #include <nvramlog.h>
14 #include <southbridge.h>
15 #include <calculatecrc.h>
16
17 #if !defined(DISABLE_NVRAM) && !defined(RTAS_NVRAM)
18
19 // detect overflow: if(a<b)  return a else return 0
20 #define NVRAM_LOG_DATA_OVERFLOW( a, b) \
21         cmpd    7, a, b; \
22         blt+    7, 0f; \
23         li      a, 0; \
24         0:
25
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
39
40 /****************************************************************************
41  *      checkLogHeaderData
42  *      compare the fixed values in the header if any change was done since
43  *      last initialisation.
44  *      Flags are not checked!
45  *
46  *      Retrun 0 if no manimulation was found 1 else
47  *
48  *      input:
49  *                      r3 - NVRAM Base Address 
50  *
51  *      output:
52  *                      r3 - status: 0 = ok, 1 = corrupt
53  *                      r4 - NVRAM Base Address
54  *
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
60         add     r4, r4, r5
61
62         lhz     r5, LLFW_LOG_POS_LENGTH(r3)             // check length
63         addi    r5, r5, -LLFW_LOG_BE0_LENGTH
64         add     r4, r4, r5
65
66         lwz     r5, LLFW_LOG_POS_NAME(r3)               // check name prefix
67         LOAD64( r6, LLFW_LOG_BE0_NAME_PREFIX)
68         subf    r5, r6, r5
69         add     r4, r4, r5
70
71         ld      r5, (LLFW_LOG_POS_NAME+4)(r3)           // check name
72         LOAD64( r6, LLFW_LOG_BE0_NAME)
73         subf    r5, r6, r5
74         add     r4, r4, r5
75         
76         lhz     r5, LLFW_LOG_POS_DATA_OFFSET(r3)        //check data offset
77         addi    r5, r5, -LLFW_LOG_BE0_DATA_OFFSET
78         add     r4, r4, r5
79
80         lhz     r5, LLFW_LOG_POS_FLAGS(r3)              //check flags
81         addi    r5, r5, -LLFW_LOG_BE0_FLAGS
82         add     r4, r4, r5
83
84         cmpldi  7, r4, 0
85         beq+    7, 0f
86         li      r4, 1
87 0:
88         mr      r5, r3
89         mr      r3, r4
90         mr      r4, r5
91         blr
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
99  *                                              
100  *      input:  
101  *              r3 - NVRAM log address (BASE + NVRAM_LOG_OFFSET)
102  *
103  *      output: 
104  *              r3 - CRC status  
105  *              r4 - NVRAM log address
106  *
107  *      Modifies Register:      R3, R4, R5, R6, R7, R8, R9
108  ****************************************************************************/
109 ASM_ENTRY(.checkLogPartition)
110         mflr    r8
111         mr      r4, r3                  // emulate "bl updateCRC_NVRAM"
112         li      r3, 0                   // with successful CRC check
113         li      r7, 0
114         cmpwi   7, r3, 0
115         beq+    7, 0f
116         li      r7, 2
117 0:
118         mr      r3, r4
119         bl      .calPartitionHeaderChecksum     // r3=checksum, r4=NVARM addr
120         lbz     r6, LLFW_LOG_POS_CHECKSUM(r4)
121         cmpw    7, r3, r6
122         beq+    7, 0f                   // cal checksum must eq checksum
123         ori     r7, r7, 1
124 0:
125         cmpwi   7, r3, 0
126         bne+    7, 0f
127         ori     r7, r7, 1               // 0 as checksum is invalid
128 0:
129         mr      r3, r4
130         bl      checkLogHeaderData      
131         cmpdi   7, r3, 0
132         beq+    7, 0f
133         ori     r7, r7, 4
134 0:
135         mr      r3, r7
136         mtlr    r8
137         blr
138 /*****************************************************************************
139  * checkinitLog:        check the NVRAM Log Partition Header 
140  *                      initialize the NVRAM if the Header was modified
141  *                                      
142  *      input:  
143  *              r3 - NVRAM BASE address 
144  *
145  *      output: 
146  *              r3 - 0 = check ok, no new header written
147  *              r3 - 1 = check not ok, header and NVRAM initialized
148  *              r4 - NVRAM log address
149  *
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)
155         mflr    r9
156         bl      .checkLogPartition              //r3..r8, r4_out = r3_in   
157         mtlr    r9
158         
159         cmpwi   7, r3, 0
160         mr      r3, r4                  // r3=NVRAM_LOG address
161         bne-    7, .initLog             // if header is not ok, init header
162         li      r3, 0
163         blr                             // header OK, return 0                  
164
165
166 /* this is basically just a copy of .initLog 
167    registers used: r3, r4, r5, r6, r7, r9*/
168 init_log_2nd_be:
169         mflr    r9      
170         li      r6, LLFW_LOG_BE0_LENGTH
171         mulli   r6, r6, 0x10
172         add     r6, r7, r6
173         li      r5, LLFW_LOG_BE1_SIGNATURE
174         li      r4, LLFW_LOG_BE1_LENGTH
175         stb     r5, 0(r6)
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)
181         li      r5, 1
182
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)
188         mr      r3, r6
189         bl      .calPartitionHeaderChecksum
190         stb     r3, LLFW_LOG_POS_CHECKSUM(r6)
191         mtlr    r9
192         blr
193 /*****************************************************************************
194  * initLog:     initialize the NVRAM with 0
195  *              write a new NVRAM Log-Partition-Header
196  *                                      
197  *      input:  
198  *              r3 - NVRAM BASE address 
199  *
200  *      output: 
201  *              r3 - 0 = check ok, no new header written
202  *              r3 - 1 = check not ok, header and NVRAM initialized
203  *              r4 - NVRAM log address
204  *
205  *      Modifies Register:      R3, R4, R5, R6, R7, r8, r9
206  ****************************************************************************/
207 ASM_ENTRY(.initLog)
208         mflr    r8
209         mr      r7, r3
210
211         bl clearNVRAM
212 0:
213         li      r5, LLFW_LOG_BE0_SIGNATURE
214         li      r4, LLFW_LOG_BE0_LENGTH
215         stb     r5, 0(r7)
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)
221         li      r5, 1
222
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
231         mr      r4, r7
232         li      r3, 1
233         mtlr    r8
234         blr
235 /*****************************************************************************
236  *      clearNVRAM:     set all not used NVRAM memory to zero
237  *
238  *
239  *      input:  
240  *              R3 - NVRAM BASE ADDRESS
241  *
242  *      output: 
243  *              R3 - NVARM END ADDRESS
244  *
245  *      Modifies Register: r4, r5
246  ****************************************************************************/
247 ASM_ENTRY(clearNVRAM)
248         LOAD64( r4, NVRAM_LENGTH)
249         srdi    r4, r4, 3
250         mtctr   r4
251         li      r5, 0x0
252         LOAD64( r4, NVRAM_EMPTY_PATTERN)
253 0:
254         stdx    r4, r3,r5
255         addi    r5, r5, 8
256         bdnz+   0b
257         blr     
258 /*****************************************************************************
259  * writeNVRAMbyte:      write next log into NVRAM
260  *                                      
261  *
262  *      input:  
263  *              R3 - byte to be written
264  *              R4 - NVRAM Base Address
265  *
266  *      output: 
267  *              R3 - byte that was written
268  *              R4 - NVRAM Base Address 
269  *
270  *      Modifies Register:      R3, R4, R5, R6
271  ****************************************************************************/
272 ASM_ENTRY(.writeNVRAMbyte)
273 ENTRY(writeLogByte)
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 
280
281         stb     r3, LLFW_LOG_BE0_DATA_OFFSET(r6)        
282         blr
283
284 /*****************************************************************************
285  * writeNVRAMbyte:      write next log into NVRAM
286  *                                      
287  *
288  *      input:  
289  *              R3 - byte to be written
290  *              R4 - NVRAM Base Address
291  *
292  *      output: 
293  *              R3 - byte that was written
294  *              R4 - NVRAM Base Address 
295  *
296  *      Modifies Register:      R3, R4, R5, R6
297  ****************************************************************************/
298 ENTRY(writeLogByteBE1)
299         li      r6, LLFW_LOG_BE0_LENGTH
300         mulli   r6, r6, 0x10
301         add     r4, r6, r4
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 
308
309         stb     r3, LLFW_LOG_BE1_DATA_OFFSET(r6)        
310         blr
311
312 /*****************************************************************************
313  * calPartitionHeaderChecksum:  calculate the Checksum of the 
314  *      Partition Header as described in ....
315  *
316  *      input: r3 - NVRAM BASE adresse
317  *
318  *      output: R3 - the calculated checksum as 8 bit value 
319  *                      R4 - NVRAM log address
320  *
321  *      Modifies Register:      R3, R4, R5, R6
322  ****************************************************************************/
323 ASM_ENTRY(.calPartitionHeaderChecksum)
324         mr      r6, r3
325         lbz     r3,0(r6)                        // load first byte
326         LOAD64( r4, LLFW_LOG_POS_LENGTH)        // load position of 3rd byte
327 .L6:
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
331         rldicl  r5, r5, 0, 56
332         cmpld   7, r5, r3                                       
333         cmpldi  6, r4, LLFW_LOG_POS_DATA_OFFSET
334         bge+    7,.L5                           // if new sum > sum 
335         addi    r5, r5, 1                       // new sum ++
336         rldicl  r5, r5, 0, 56
337 .L5:
338         mr      r3,r5                           // sum = new sum
339         blt+    6,.L6
340
341         mr r4, r6
342         blr
343
344 #else   /* defined(DISABLE_NVRAM) || defined(RTAS_NVRAM) */
345
346 ASM_ENTRY(.writeNVRAMbyte)
347         ENTRY(writeLogByte)
348         blr
349
350 #endif