|
|
1.1 ! root 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 short manage_flash_buffer[BUFSIZE]; ! 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: 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 *)((void*)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] = 0; ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.