|
|
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:
1.1.1.2 root 37: unsigned char manage_flash_buffer[BUFSIZE*2];
1.1 root 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:
1.1.1.3 ! root 219: static void
1.1 root 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);
1.1.1.2 root 256: uint64_t *destPtr = (uint64_t *)manage_flash_buffer;
1.1 root 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();
1.1.1.2 root 336: rtas_args->args[rtas_args->nargs] = result;
1.1 root 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.