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 *****************************************************************************/
19 #include "rtas_board.h"
21 #include "rtas_flash.h"
22 #include <flash/block_lists.h>
24 #include "calculatecrc.h"
29 #define dprintf(_x ...) printf(_x)
31 #define dprintf(_x ...)
35 static uint64_t flashOffset;
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);
43 dump_blocklist(uint64_t *bl, int version)
46 uint8_t *addr = (uint8_t *)bl;
49 /* version 1 blocklist */
50 bl_size = *bl & 0x00FFFFFFFFFFFFFFUL;
56 printf("\n\rblocklist_dump %lx", bl_size);
58 unsigned int tmpCnt = bl_size;
62 printf("\n\r%08x: ", addr);
74 /* reset addr ptr to print ascii */
81 if ((x < 32) || (x >= 127)) {
82 /* non-printable char */
93 rtas_dump_flash(rtas_args_t *rtas_args)
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;
100 printf("\n\rflash_dump %x %x", size, offset);
103 unsigned int tmpCnt = size;
107 printf("\n\r%p: ", flash);
119 /* reset flash ptr to print ascii */
120 flash = flash - tmpCnt;
126 if ((x < 32) || (x >= 127)) {
127 /* non-printable char */
134 rtas_args->args[rtas_args->nargs] = retVal;
150 /* To enter data mode after flash has been in programming mode
151 * a 0xFF has to be written */
153 enter_data_mode(void)
155 volatile unsigned char *flash = (volatile unsigned char *)FLASH;
165 erase_flash_block(unsigned long offset)
167 volatile unsigned char *flash = (volatile unsigned char *)FLASH;
175 while (!(*flash & 0x80)) ;
181 write_flash(unsigned long offset, unsigned char *data)
184 volatile unsigned char *flash = (volatile unsigned char *)FLASH;
186 flash += (offset + flashOffset);
189 if (!((uint64_t)flash & 0x1F)) {
191 uint64_t tmpcnt = cnt;
197 } while (!(*flash & 0x80));
205 while (!(*flash & 0x80)) ;
213 while (!(*flash & 0x80)) ;
220 write_flash_page(unsigned long offset, unsigned short *data)
224 for (i = 0; i < BUFSIZE; i += 32, offset += 32) {
225 write_flash(offset, ((unsigned char *)data + i));
230 * 0 reject temporary image
231 * 1 commit temporary image
234 copy_flash(short mode)
236 volatile unsigned char *flash = (volatile unsigned char *)FLASH;
239 short notmode = mode ^ 0x1;
241 if (bmc_set_flashside(notmode) != notmode) {
244 printf("\r\nErasing Flash: 0x ");
246 for (blockCnt = 0; blockCnt <= FLASHSIZE; blockCnt += FLASH_BLOCK_SIZE) {
247 print_block(blockCnt);
248 erase_flash_block(blockCnt);
251 progress = FLASHSIZE / 38;
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) {
264 *destPtr++ = *srcPtr++;
268 if (bmc_set_flashside(notmode) != notmode) {
271 write_flash_page(blockCnt,
272 (unsigned short *)manage_flash_buffer);
274 /* progress output... */
276 if (blockCnt > hash * progress) {
282 if (bmc_set_flashside(mode) != mode) {
290 * Function: ibm_manage_flash_image
292 * r3: rtas parm structure
296 * parm0: 0 reject temporary image
297 * 1 commit temporary image
299 * parm1: Status (hw -1, busy -2, parameter error -3
300 * -9001 cannot overwrite the active firmware image)
305 rtas_ibm_manage_flash_image(rtas_args_t *rtas_args)
309 short mode = rtas_args->args[0];
311 if (mode < 0 || mode > 1) {
312 rtas_args->args[rtas_args->nargs] = -3;
315 side = bmc_get_flashside();
317 /* we are on the permanent side */
319 rtas_args->args[rtas_args->nargs] = -9001;
322 } else if (side == 1) {
323 /* we are on the temporary side */
325 rtas_args->args[rtas_args->nargs] = -9001;
329 rtas_args->args[rtas_args->nargs] = -1;
333 result = copy_flash(mode);
334 bmc_set_flashside(mode);
336 rtas_args->args[rtas_args->nargs] = result;
340 * check, if we find the FLASHFS_MAGIC token in bl
343 check_magic(uint64_t *bl, int version)
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];
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);
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);
367 get_image_name(char *buffer, int maxsize)
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;
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';
382 addr = (uint64_t)flash_header->version;
384 *buffer = load8_ci(addr++);
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:
401 * @param args[3] - update result token
404 rtas_ibm_validate_flash_image(rtas_args_t *rtas_args)
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();
415 /* fill args[0] with the current values which is needed
416 * in an error case */
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);
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);
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);
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);
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;
466 if (strncmp(new_version, current_temp_version, 16) >= 0)
467 rtas_args->args[rtas_args->nargs + 1] = 0;
469 rtas_args->args[rtas_args->nargs + 1] = 6;
473 * Function: ibm_update_flash_64
475 * r3: rtas parm structure
479 * parm0: A real pointer to a block list
481 * parm1: Status (hw -1, bad image -3, programming failed -4)
483 * Description: flash if addresses above 4GB have to be addressed
486 rtas_update_flash(rtas_args_t *rtas_args)
488 void *bl = (void *)(uint64_t)rtas_args->args[0];
489 int version = get_block_list_version((unsigned char *)bl);
495 dump_blocklist(bl, version);
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))
503 /* check magic string */
504 printf("\r\nChecking magic string : ");
505 if (check_magic(bl, version) != 0) {
507 rtas_args->args[rtas_args->nargs] = -3; /* bad image */
510 printf("succeeded!\n");
513 printf("Checking platform : ");
514 if (check_platform(bl, 0x48, version) == -1) {
516 rtas_args->args[rtas_args->nargs] = -3; /* bad image */
519 printf("succeeded!\n");
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) {
526 rtas_args->args[1] = -3; /* bad image */
529 printf("succeeded!\n");
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);
541 ra.args[0] = 0x100; /* size; */
542 ra.args[1] = flashOffset;
545 rtas_dump_flash(&ra);
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);
554 progress = size / 39;
555 printf("Erasing : 0x%08x", 0);
556 for (i = 0; i < erase_size; i += FLASH_BLOCK_SIZE) {
558 erase_flash_block(i);
563 rtas_dump_flash(&ra);
567 write_block_list(bl, version);
572 rtas_dump_flash(&ra);
577 printf("Recheck CRC : ");
578 if (check_flash_image(FLASH + flashOffset, size, 0) != 0) {
580 printf("failed!\n\r");
581 dprintf("flash_addr: %#x, flashOffset: %#x, size: %#x\n", FLASH,
583 dprintf("crc: %#x\n",
584 check_flash_image(FLASH + flashOffset, size, 0));
585 rtas_args->args[rtas_args->nargs] = -4; /* programming failed */
588 printf("succeeded!\n");
589 rtas_args->args[rtas_args->nargs] = 0;
593 * Function: ibm_update_flash_64_and_reboot
595 * r3: rtas parm structure
599 * parm0: A real pointer to a block list
601 * parm1: Status (hw -1, bad image -3, programming failed -4)
602 * Currently -4 and -1 are not returned
604 * Description: flash and reboot if addresses above 4GB have to be addressed
607 rtas_ibm_update_flash_64_and_reboot(rtas_args_t *rtas_args)
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);