Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / SLOF / board-js2x / rtas / rtas_flash.c
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
13 #include <cpu.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <hw.h>
18 #include <rtas.h>
19 #include "rtas_board.h"
20 #include <bmc.h>
21 #include "rtas_flash.h"
22 #include <flash/block_lists.h>
23 #include "product.h"
24 #include "calculatecrc.h"
25
26 #undef DEBUG
27
28 #ifdef DEBUG
29 #define dprintf(_x ...) printf(_x)
30 #else
31 #define dprintf(_x ...)
32 #endif
33
34 static uint64_t size;
35 static uint64_t flashOffset;
36
37 unsigned char manage_flash_buffer[BUFSIZE*2];
38 unsigned long check_flash_image(unsigned long rombase, unsigned long length,
39                                 unsigned long start_crc);
40
41 #ifdef DEBUG
42 static void
43 dump_blocklist(uint64_t *bl, int version)
44 {
45         uint64_t bl_size;
46         uint8_t *addr = (uint8_t *)bl;
47
48         if (version == 1) {
49                 /* version 1 blocklist */
50                 bl_size = *bl & 0x00FFFFFFFFFFFFFFUL;
51
52         } else {
53                 bl_size = *bl;
54         }
55
56         printf("\n\rblocklist_dump %lx", bl_size);
57         while (bl_size) {
58                 unsigned int tmpCnt = bl_size;
59                 unsigned char x;
60                 if (tmpCnt > 8)
61                         tmpCnt = 8;
62                 printf("\n\r%08x: ", addr);
63                 /* print hex */
64                 while (tmpCnt--) {
65                         set_ci();
66                         x = *addr++;
67                         clr_ci();
68                         printf("%02x ", x);
69                 }
70                 tmpCnt = bl_size;
71                 if (tmpCnt > 8)
72                         tmpCnt = 8;
73                 bl_size -= tmpCnt;
74                 /* reset addr ptr to print ascii */
75                 addr = addr - tmpCnt;
76                 /* print ascii */
77                 while (tmpCnt--) {
78                         set_ci();
79                         x = *addr++;
80                         clr_ci();
81                         if ((x < 32) || (x >= 127)) {
82                                 /* non-printable char */
83                                 x = '.';
84                         }
85                         printf("%c", x);
86                 }
87         }
88         printf("\r\n");
89 }
90 #endif
91
92 void
93 rtas_dump_flash(rtas_args_t *rtas_args)
94 {
95         int retVal = 0;
96         unsigned int size = rtas_args->args[0];
97         unsigned int offset = rtas_args->args[1];
98         volatile unsigned char *flash = (volatile unsigned char *)FLASH;
99
100         printf("\n\rflash_dump %x %x", size, offset);
101         flash += offset;
102         while (size) {
103                 unsigned int tmpCnt = size;
104                 unsigned char x;
105                 if (tmpCnt > 16)
106                         tmpCnt = 16;
107                 printf("\n\r%p: ", flash);
108                 /* print hex */
109                 while (tmpCnt--) {
110                         set_ci();
111                         x = *flash++;
112                         clr_ci();
113                         printf("%02x ", x);
114                 }
115                 tmpCnt = size;
116                 if (tmpCnt > 16)
117                         tmpCnt = 16;
118                 size -= tmpCnt;
119                 /* reset flash ptr to print ascii */
120                 flash = flash - tmpCnt;
121                 /* print ascii */
122                 while (tmpCnt--) {
123                         set_ci();
124                         x = *flash++;
125                         clr_ci();
126                         if ((x < 32) || (x >= 127)) {
127                                 /* non-printable char */
128                                 x = '.';
129                         }
130                         printf("%c", x);
131                 }
132         }
133         printf("\r\n");
134         rtas_args->args[rtas_args->nargs] = retVal;
135 }
136
137
138 static void
139 print_block(int i)
140 {
141         int counter = 8;
142
143         while (counter--)
144                 printf("\b");
145         printf("%08x", i);
146 }
147
148
149
150 /* To enter data mode after flash has been in programming mode
151  * a 0xFF has to be written */
152 static void
153 enter_data_mode(void)
154 {
155         volatile unsigned char *flash = (volatile unsigned char *)FLASH;
156
157         set_ci();
158         *flash = 0xFF;
159         eieio();
160         clr_ci();
161 }
162
163
164 static void
165 erase_flash_block(unsigned long offset)
166 {
167         volatile unsigned char *flash = (volatile unsigned char *)FLASH;
168
169         flash += offset;
170         set_ci();
171         *flash = 0x20;
172         eieio();
173         *flash = 0xd0;
174         eieio();
175         while (!(*flash & 0x80)) ;
176         clr_ci();
177 }
178
179
180 void
181 write_flash(unsigned long offset, unsigned char *data)
182 {
183         int cnt = 32;
184         volatile unsigned char *flash = (volatile unsigned char *)FLASH;
185
186         flash += (offset + flashOffset);
187         set_ci();
188         while (cnt) {
189                 if (!((uint64_t)flash & 0x1F)) {
190                         while (cnt) {
191                                 uint64_t tmpcnt = cnt;
192                                 if (tmpcnt > 0x20)
193                                         tmpcnt = 0x20;
194                                 do {
195                                         *flash = 0xE8;
196                                         eieio();
197                                 } while (!(*flash & 0x80));
198                                 cnt -= tmpcnt;
199                                 *flash = tmpcnt - 1;
200                                 while (tmpcnt--) {
201                                         *flash++ = *data++;
202                                 }
203                                 *flash = 0xD0;
204                                 eieio();
205                                 while (!(*flash & 0x80)) ;
206                         }
207                         break;
208                 }
209                 *flash = 0x40;
210                 eieio();
211                 *flash++ = *data++;
212                 eieio();
213                 while (!(*flash & 0x80)) ;
214                 cnt--;
215         }
216         clr_ci();
217 }
218
219 static void
220 write_flash_page(unsigned long offset, unsigned short *data)
221 {
222         int i = 0;
223
224         for (i = 0; i < BUFSIZE; i += 32, offset += 32) {
225                 write_flash(offset, ((unsigned char *)data + i));
226         }
227 }
228
229 /*
230  * 0 reject temporary image
231  * 1 commit temporary image
232  * */
233 static int
234 copy_flash(short mode)
235 {
236         volatile unsigned char *flash = (volatile unsigned char *)FLASH;
237         uint64_t blockCnt;
238         uint64_t hash = 0;
239         short notmode = mode ^ 0x1;
240
241         if (bmc_set_flashside(notmode) != notmode) {
242                 return -1;
243         }
244         printf("\r\nErasing Flash: 0x        ");
245
246         for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += FLASH_BLOCK_SIZE) {
247                 print_block(blockCnt);
248                 erase_flash_block(blockCnt);
249         }
250         enter_data_mode();
251         progress = FLASHSIZE / 38;
252         print_writing();
253
254         for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += BUFSIZE) {
255                 uint64_t *srcPtr = (uint64_t *)(flash + blockCnt);
256                 uint64_t *destPtr = (uint64_t *)manage_flash_buffer;
257                 uint64_t cnt = BUFSIZE / 8;
258                 if (bmc_set_flashside(mode) != mode) {
259                         return -1;
260                 }
261                 enter_data_mode();
262                 set_ci();
263                 while (cnt--) {
264                         *destPtr++ = *srcPtr++;
265                 }
266                 clr_ci();
267
268                 if (bmc_set_flashside(notmode) != notmode) {
269                         return -1;
270                 }
271                 write_flash_page(blockCnt,
272                                  (unsigned short *)manage_flash_buffer);
273
274                 /* progress output... */
275                 print_progress();
276                 if (blockCnt > hash * progress) {
277                         print_hash();
278                         hash++;
279                 }
280         }
281         enter_data_mode();
282         if (bmc_set_flashside(mode) != mode) {
283                 return -1;
284         }
285         printf("\b#\n");
286         return 0;
287 }
288
289 /*
290  * Function: ibm_manage_flash_image
291  *      Input:
292  *              r3:   rtas parm structure
293  *                      token:  46
294  *                      in:     1
295  *                      out:    1
296  *                      parm0:  0 reject temporary image
297  *                              1 commit temporary image
298  *      Output:
299  *                      parm1:  Status (hw -1, busy -2, parameter error -3
300  *                                      -9001 cannot overwrite the active firmware image)
301  *
302  */
303
304 void
305 rtas_ibm_manage_flash_image(rtas_args_t *rtas_args)
306 {
307         int side;
308         int result = 0;
309         short mode = rtas_args->args[0];
310
311         if (mode < 0 || mode > 1) {
312                 rtas_args->args[rtas_args->nargs] = -3;
313                 return;
314         }
315         side = bmc_get_flashside();
316         if (side == 0) {
317                 /* we are on the permanent side */
318                 if (mode != 0) {
319                         rtas_args->args[rtas_args->nargs] = -9001;
320                         return;
321                 }
322         } else if (side == 1) {
323                 /* we are on the temporary side */
324                 if (mode != 1) {
325                         rtas_args->args[rtas_args->nargs] = -9001;
326                         return;
327                 }
328         } else {
329                 rtas_args->args[rtas_args->nargs] = -1;
330                 return;
331         }
332
333         result = copy_flash(mode);
334         bmc_set_flashside(mode);
335         enter_data_mode();
336         rtas_args->args[rtas_args->nargs] = result;
337 }
338
339 /**
340  * check, if we find the FLASHFS_MAGIC token in bl
341  **/
342 static uint8_t
343 check_magic(uint64_t *bl, int version)
344 {
345         struct stH *pHeader;
346
347         if (version == 1) {
348                 /* version 1 blocklist */
349                 /* if block list size <= 0x10, it is only block list header */
350                 /* and address of block list extension, so look at the extension... */
351                 while ((*bl & 0x00FFFFFFFFFFFFFFUL) <= 0x10)
352                         bl = (uint64_t *)bl[1];
353
354                 /* block list item 2 _should_ be the address of our flashfs image */
355                 pHeader = (struct stH *)(bl[2] + 0x28);
356                 /* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */
357                 return strncmp(pHeader->magic, FLASHFS_MAGIC, 8);
358         } else {
359                 /* block list item 1 _should_ be the address of our flashfs image */
360                 pHeader = (struct stH *)(bl[1] + 0x28);
361                 /* printf("FlashFS Magic: \"%#s\"\r\n", pHeader->magic); */
362                 return strncmp(pHeader->magic, FLASHFS_MAGIC, 8);
363         }
364 }
365
366 static void
367 get_image_name(char *buffer, int maxsize)
368 {
369         volatile struct stH *flash_header = (volatile struct stH *)(SB_FLASH_adr + 0x28);
370         /* since we cannot read the fh_magic directly from flash as a string, we need to copy it to memory */
371         uint64_t magic_val = 0;
372         uint64_t addr;
373
374         /* copy fh_magic to magic_val since, we cannot use it as a string from flash */
375         magic_val = load64_ci((uint64_t)(flash_header->magic));
376         if (strncmp((char *)&magic_val, FLASHFS_MAGIC, 8)) {
377                 /* magic does not match */
378                 sprintf(buffer, "Unknown");
379                 buffer[maxsize - 1] = '\0';
380                 return;
381         }
382         addr = (uint64_t)flash_header->version;
383         while (--maxsize) {
384                 *buffer = load8_ci(addr++);
385                 if (!*buffer++)
386                         return;
387         }
388         *buffer = '\0';
389 }
390
391 /**
392  * validate_flash_image
393  * this function checks if the flash will be updated with the given image
394  * @param args[0] - buffer with minimum 4K of the image to flash
395  * @param args[1] - size of the buffer
396  * @param args[2] - status:
397  *                           0    success
398  *                          -1    hw
399  *                          -2    busy
400  *                          -3    parameter error
401  * @param args[3] - update result token
402  */
403 void
404 rtas_ibm_validate_flash_image(rtas_args_t *rtas_args)
405 {
406         dprintf("\nrtas_ibm_validate_flash_image\n");
407         unsigned long new_image = rtas_args->args[0];
408         char *ret_str = (char *)new_image;
409         struct stH *flash_header = (struct stH *)(new_image + 0x28);
410         char current_temp_version[16];
411         char current_perm_version[16];
412         char new_version[16];
413         int side = bmc_get_flashside();
414
415         /* fill args[0] with the current values which is needed
416          * in an error case */
417
418         bmc_set_flashside(0);
419         get_image_name(current_perm_version, sizeof(current_perm_version));
420         bmc_set_flashside(1);
421         get_image_name(current_temp_version, sizeof(current_temp_version));
422         bmc_set_flashside(side);
423
424         /* check if the candidate image if valid for this platform */
425         if (strncmp(flash_header->magic, FLASHFS_MAGIC, 8)) {
426                 /* magic does not match */
427                 rtas_args->args[rtas_args->nargs] = 0;
428                 /* No update done, the candidate image is
429                  * not valid for this platform */
430                 rtas_args->args[rtas_args->nargs + 1] = 2;
431                 sprintf(ret_str, "MI %s %s\xaMI %s %s",
432                         current_temp_version, current_perm_version,
433                         current_temp_version, current_perm_version);
434                 return;
435         }
436
437         if (strncmp(flash_header->platform_name, (char *)sig_org, 32)) {
438                 /* this image if for a different board */
439                 rtas_args->args[rtas_args->nargs] = 0;
440                 /* No update done, the candidate image is
441                  * not valid for this platform */
442                 rtas_args->args[rtas_args->nargs + 1] = 2;
443                 sprintf(ret_str, "MI %s %s\xaMI %s %s",
444                         current_temp_version, current_perm_version,
445                         current_temp_version, current_perm_version);
446                 return;
447         }
448
449         /* check header crc */
450         if (check_flash_image(rtas_args->args[0], 0x88, 0)) {
451                 /* header crc failed */
452                 rtas_args->args[rtas_args->nargs] = 0;
453                 /* No update done, the candidate image is
454                  * not valid for this platform */
455                 rtas_args->args[rtas_args->nargs + 1] = 2;
456                 sprintf(ret_str, "MI %s %s\xaMI %s %s",
457                         current_temp_version, current_perm_version,
458                         current_temp_version, current_perm_version);
459                 return;
460         }
461         memcpy(new_version, flash_header->version, 16);
462         sprintf(ret_str, "MI %s %s\xaMI %s %s", current_temp_version,
463                 current_perm_version, new_version, current_perm_version);
464         rtas_args->args[rtas_args->nargs] = 0;
465
466         if (strncmp(new_version, current_temp_version, 16) >= 0)
467                 rtas_args->args[rtas_args->nargs + 1] = 0;
468         else
469                 rtas_args->args[rtas_args->nargs + 1] = 6;
470 }
471
472 /*
473  * Function: ibm_update_flash_64
474  *      Input:
475  *              r3:   rtas parm structure
476  *                      token:  7
477  *                      in:     1
478  *                      out:    1
479  *                      parm0:  A real pointer to a block list
480  *      Output:
481  *                      parm1:  Status (hw -1, bad image -3, programming failed -4)
482  *
483  *   Description: flash if addresses above 4GB have to be addressed
484  */
485 void
486 rtas_update_flash(rtas_args_t *rtas_args)
487 {
488         void *bl = (void *)(uint64_t)rtas_args->args[0];
489         int version = get_block_list_version((unsigned char *)bl);
490         uint64_t erase_size;
491         unsigned int i;
492         int perm_check = 1;
493
494 #ifdef DEBUG
495         dump_blocklist(bl, version);
496 #endif
497
498         /* from SLOF we pass a second (unofficial) parameter, if this parameter is 1, we do not
499          * check wether we are on permanent side. Needed for update-flash -c to work! */
500         if ((rtas_args->nargs > 1) && (rtas_args->args[1] == 1))
501                 perm_check = 0;
502
503         /* check magic string */
504         printf("\r\nChecking magic string : ");
505         if (check_magic(bl, version) != 0) {
506                 printf("failed!\n");
507                 rtas_args->args[rtas_args->nargs] = -3; /* bad image */
508                 return;
509         }
510         printf("succeeded!\n");
511
512         /* check platform */
513         printf("Checking platform : ");
514         if (check_platform(bl, 0x48, version) == -1) {
515                 printf("failed!\n");
516                 rtas_args->args[rtas_args->nargs] = -3; /* bad image */
517                 return;
518         }
519         printf("succeeded!\n");
520
521         /* checkcrc */
522         printf("Checking CRC : ");
523         /* the actual CRC is included at the end of the flash image, thus the resulting CRC must be 0! */
524         if (image_check_crc(bl, version) != 0) {
525                 printf("failed!\n");
526                 rtas_args->args[1] = -3;        /* bad image */
527                 return;
528         }
529         printf("succeeded!\n");
530
531         /* check if we are running on P
532          * if so, let's switch to temp and flash temp */
533         if (bmc_get_flashside() == 0  && perm_check) {
534                 printf("Set flashside: ");
535                 bmc_set_flashside(1);
536                 printf("Temp!\n");
537         }
538
539 #ifdef DEBUG
540         rtas_args_t ra;
541         ra.args[0] = 0x100;     /* size; */
542         ra.args[1] = flashOffset;
543         ra.nargs = 2;
544
545         rtas_dump_flash(&ra);
546         printf("\n");
547 #endif
548
549         size = get_size(bl, version);
550         erase_size = (size + (FLASH_BLOCK_SIZE - 1)) & ~(FLASH_BLOCK_SIZE - 1);
551         dprintf("Erasing: size: %#x, erase_size: %#x, FLASH_BLOCK_SIZE: %#x\n",
552                 size, erase_size, FLASH_BLOCK_SIZE);
553
554         progress = size / 39;
555         printf("Erasing : 0x%08x", 0);
556         for (i = 0; i < erase_size; i += FLASH_BLOCK_SIZE) {
557                 print_block(i);
558                 erase_flash_block(i);
559         }
560
561         enter_data_mode();
562 #ifdef DEBUG
563         rtas_dump_flash(&ra);
564         printf("\n");
565 #endif
566         print_writing();
567         write_block_list(bl, version);
568         printf("\b#\n");
569         enter_data_mode();
570
571 #ifdef DEBUG
572         rtas_dump_flash(&ra);
573         printf("\n");
574 #endif
575
576         /* checkcrc */
577         printf("Recheck CRC : ");
578         if (check_flash_image(FLASH + flashOffset, size, 0) != 0) {
579                 /* failed */
580                 printf("failed!\n\r");
581                 dprintf("flash_addr: %#x, flashOffset: %#x, size: %#x\n", FLASH,
582                         flashOffset, size);
583                 dprintf("crc: %#x\n",
584                         check_flash_image(FLASH + flashOffset, size, 0));
585                 rtas_args->args[rtas_args->nargs] = -4; /* programming failed */
586                 return;
587         }
588         printf("succeeded!\n");
589         rtas_args->args[rtas_args->nargs] = 0;
590 }
591
592 /*
593  * Function: ibm_update_flash_64_and_reboot
594  *      Input:
595  *              r3:   rtas parm structure
596  *                      token:  27
597  *                      in:     1
598  *                      out:    1
599  *                      parm0:  A real pointer to a block list
600  *      Output:
601  *                      parm1:  Status (hw -1, bad image -3, programming failed -4)
602  *                              Currently -4 and -1 are not returned
603  *
604  *  Description: flash and reboot if addresses above 4GB have to be addressed
605  */
606 void
607 rtas_ibm_update_flash_64_and_reboot(rtas_args_t *rtas_args)
608 {
609         rtas_update_flash(rtas_args);
610         dprintf("rc: %#d\n", rtas_args->args[rtas_args->nargs]);
611         if (rtas_args->args[rtas_args->nargs] == 0) {
612                 rtas_system_reboot(rtas_args);
613         }
614 }