summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c')
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c1375
1 files changed, 1375 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c
new file mode 100755
index 0000000..91e1ad0
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_util.c
@@ -0,0 +1,1375 @@
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * bcm63xx utility functions
+ *
+ * Created on : 04/18/2002 seanl
+ *
+ *********************************************************************
+
+<:copyright-broadcom
+
+ Copyright (c) 2002 Broadcom Corporation
+ All Rights Reserved
+ No portions of this material may be reproduced in any form without the
+ written permission of:
+ Broadcom Corporation
+ 16215 Alton Parkway
+ Irvine, California 92619
+ All information contained in this document is Broadcom Corporation
+ company private, proprietary, and trade secret.
+
+:>
+*/
+
+#define BCMTAG_EXE_USE
+#include "bcm63xx_util.h"
+#include "flash_api.h"
+#include "jffs2.h"
+
+#define je16_to_cpu(x) ((x).v16)
+#define je32_to_cpu(x) ((x).v32)
+
+static void convertBootInfo(void);
+static int checkChipId(int tagChipId, char *sig2);
+static void UpdateImageSequenceNumber( char *imageSequence );
+
+BOOT_INFO bootInfo;
+
+static int parseFilename(char *fn)
+{
+ if (strlen(fn) < BOOT_FILENAME_LEN)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseChoiceFh(char *choice)
+{
+
+ if (*choice == 'f' || *choice == 'h')
+ return 0;
+ else
+ return 1;
+}
+
+
+static int parseBootPartition(char *choice)
+{
+ return( (*choice == BOOT_LATEST_IMAGE || *choice == BOOT_PREVIOUS_IMAGE)
+ ? 0 : 1 );
+}
+
+static int parseChoice09(char *choice)
+{
+ int bChoice = *choice - '0';
+
+ if (bChoice >= 0 && bChoice <= 9)
+ return 0;
+ else
+ return 1;
+}
+
+static int parseIpAddr(char *ipStr);
+static int parseGwIpAddr(char *ipStr);
+static int parseAfeId(char *afeIdStr);
+
+#define PARAM_IDX_BOARD_IPADDR 0
+#define PARAM_IDX_HOST_IPADDR 1
+#define PARAM_IDX_GW_IPADDR 2
+#define PARAM_IDX_RUN_FROM 3
+#define PARAM_IDX_RUN_FILENAME 4
+#define PARAM_IDX_FLASH_FILENAME 5
+#define PARAM_IDX_BOOT_DELAY 6
+#define PARAM_IDX_BOOT_IMAGE 7
+
+static PARAMETER_SETTING gBootParam[] =
+{
+ // prompt name Error Prompt Boot Define Boot Param Validation function
+ {"Board IP address :", IP_PROMPT , "e=",
+ "", 24, parseIpAddr, TRUE}, // index 0
+ {"Host IP address :", IP_PROMPT , "h=",
+ "", 15, parseIpAddr, TRUE}, // index 1
+ {"Gateway IP address :", IP_PROMPT , "g=",
+ "", 15, parseGwIpAddr, TRUE}, // index 2
+ {"Run from flash/host (f/h) :", RUN_FROM_PROMPT , "r=",
+ "", 1, parseChoiceFh, TRUE}, // index 3
+ {"Default host run file name :", HOST_FN_PROMPT , "f=",
+ "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 4
+ {"Default host flash file name :", FLASH_FN_PROMPT , "i=",
+ "", MAX_PROMPT_LEN - 1, parseFilename, TRUE}, // index 5
+ {"Boot delay (0-9 seconds) :", BOOT_DELAY_PROMPT, "d=",
+ "", 1, parseChoice09, TRUE}, // index 6
+ {"Boot image (0=latest, 1=previous) :", BOOT_PARTITION_PROMPT, "p=",
+ "", 1, parseBootPartition, TRUE}, // index 7
+ {NULL},
+};
+
+static int gNumBootParams = (sizeof(gBootParam) / sizeof(PARAMETER_SETTING))-1;
+
+static PARAMETER_SETTING gAfeId[] =
+{
+ // prompt name Error Prompt Boot Define Boot Param Validation function
+ {"Primary AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 0
+ {"Bonding AFE ID :", AFE_PROMPT, "", "", 12, parseAfeId, TRUE}, // index 1
+ {NULL},
+};
+static int gAfeIdParams = (sizeof(gAfeId) / sizeof(PARAMETER_SETTING))-1;
+
+// move from lib_misc.c
+int parseipaddr(const char *ipaddr,uint8_t *dest)
+{
+ int a,b,c,d;
+ char *x;
+
+ /* make sure it's all digits and dots. */
+ x = (char *) ipaddr;
+ while (*x) {
+ if ((*x == '.') || ((*x >= '0') && (*x <= '9'))) {
+ x++;
+ continue;
+ }
+ return -1;
+ }
+
+ x = (char *) ipaddr;
+ a = lib_atoi(ipaddr);
+ x = lib_strchr(x,'.');
+ if (!x) return -1;
+ b = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ c = lib_atoi(x+1);
+ x = lib_strchr(x+1,'.');
+ if (!x) return -1;
+ d = lib_atoi(x+1);
+
+ if ((a < 0) || (a > 255)) return -1;
+ if ((b < 0) || (b > 255)) return -1;
+ if ((c < 0) || (c > 255)) return -1;
+ if ((d < 0) || (d > 255)) return -1;
+
+ dest[0] = (uint8_t) a;
+ dest[1] = (uint8_t) b;
+ dest[2] = (uint8_t) c;
+ dest[3] = (uint8_t) d;
+
+ return 0;
+}
+
+#if 0
+static const char hextable[16] = "0123456789ABCDEF";
+void dumpHex(unsigned char *start, int len)
+{
+ unsigned char *ptr = start,
+ *end = start + len;
+
+ while (ptr < end)
+ {
+ long offset = ptr - start;
+ unsigned char text[120],
+ *p = text;
+ while (ptr < end && p < &text[16 * 3])
+ {
+ *p++ = hextable[*ptr >> 4];
+ *p++ = hextable[*ptr++ & 0xF];
+ *p++ = ' ';
+ }
+ p[-1] = 0;
+ printf("%4lX %s\n", offset, text);
+ }
+}
+
+#endif
+
+int parsexdigit(char str)
+{
+ int digit;
+
+ if ((str >= '0') && (str <= '9'))
+ digit = str - '0';
+ else if ((str >= 'a') && (str <= 'f'))
+ digit = str - 'a' + 10;
+ else if ((str >= 'A') && (str <= 'F'))
+ digit = str - 'A' + 10;
+ else
+ return -1;
+
+ return digit;
+}
+
+
+// convert in = fffffff00 to out=255.255.255.0
+// return 0 = OK, 1 failed.
+static int convertMaskStr(char *in, char *out)
+{
+ int i;
+ char twoHex[4];
+ uint8_t dest[4];
+ char mask[BOOT_IP_LEN];
+
+ if (strlen(in) != MASK_LEN) // mask len has to 8
+ return 1;
+
+ memset(twoHex, 0, sizeof(twoHex));
+ for (i = 0; i < 4; i++)
+ {
+ twoHex[0] = (uint8_t)*in++;
+ twoHex[1] = (uint8_t)*in++;
+ if (parsexdigit(*twoHex) == -1)
+ return 1;
+ dest[i] = (uint8_t) xtoi(twoHex);
+ }
+ sprintf(mask, "%d.%d.%d.%d", dest[0], dest[1], dest[2], dest[3]);
+ strcpy(out, mask);
+ return 0;
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseIpAddr(char *ipStr)
+{
+ char *x;
+ uint8_t dest[4];
+ char mask[BOOT_IP_LEN];
+ char ipMaskStr[2*BOOT_IP_LEN];
+
+ strcpy(ipMaskStr, ipStr);
+
+ x = strchr(ipMaskStr,':');
+ if (!x) // no mask
+ return parseipaddr(ipMaskStr, dest);
+
+ *x = '\0';
+
+ if (parseipaddr(ipMaskStr, dest)) // ipStr is not ok
+ return 1;
+
+ x++;
+ return convertMaskStr(x, mask); // mask is not used here
+
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseGwIpAddr(char *ipStr)
+{
+ int ret = 0;
+ if( *ipStr )
+ ret = parseIpAddr(ipStr);
+ return(ret);
+}
+
+// return 0 - OK, !0 - Bad ip
+static int parseAfeId(char *afeIdStr)
+{
+ return 0;
+}
+
+// port from ifconfig command in ui_netcmds.c
+void enet_init(void)
+{
+ char devname[] = "eth0";
+ uint8_t addr[IP_ADDR_LEN];
+ int res;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ if (net_getparam(NET_DEVNAME) == NULL) {
+ res = net_init(devname); /* turn interface on */
+ if (res < 0) {
+ ui_showerror(res, "Could not activate network interface '%s'", devname);
+ return;
+ }
+ }
+
+ net_setparam(NET_HWADDR, nvramData.ucaBaseMacAddr);
+
+ parseipaddr(bootInfo.boardIp, addr);
+ net_setparam(NET_IPADDR, addr);
+
+ if (strlen(bootInfo.boardMask) > 0) {
+ parseipaddr(bootInfo.boardMask, addr);
+ net_setparam(NET_NETMASK, addr);
+ }
+
+ if (strlen(bootInfo.gatewayIp) > 0) {
+ parseipaddr(bootInfo.gatewayIp, addr);
+ net_setparam(NET_GATEWAY, addr);
+ }
+
+ net_setnetvars();
+}
+
+/***************************************************************************
+// Function Name: getCrc32
+// Description : caculate the CRC 32 of the given data.
+// Parameters : pdata - array of data.
+// size - number of input data bytes.
+// crc - either CRC32_INIT_VALUE or previous return value.
+// Returns : crc.
+****************************************************************************/
+UINT32 getCrc32(byte *pdata, UINT32 size, UINT32 crc)
+{
+ while (size-- > 0)
+ crc = (crc >> 8) ^ Crc32_table[(crc ^ *pdata++) & 0xff];
+
+ return crc;
+}
+
+
+// return 0, ok. return -1 = wrong chip
+static int checkChipId(int tagChipId, char *sig2)
+{
+ unsigned int chipId = (PERF->RevID & 0xFFFE0000) >> 16;
+ int result = 0;
+
+ /* Force BCM681x variants to be be BCM6816) */
+ if( (chipId & 0xfff0) == 0x6810 )
+ chipId = 0x6816;
+
+ if (tagChipId == chipId)
+ result = 0;
+ else {
+ printf("Chip Id error. Image Chip Id = %04x, Board Chip Id = %04x.\n", tagChipId, chipId);
+ result = -1;
+ }
+
+ return result;
+}
+
+// return -1: fail.
+// 0: OK.
+int verifyTag( PFILE_TAG pTag, int verbose )
+{
+ UINT32 crc;
+ FLASH_ADDR_INFO info;
+ int tagVer, curVer;
+
+ kerSysFlashAddrInfoGet( &info );
+
+ tagVer = atoi(pTag->tagVersion);
+ curVer = atoi(BCM_TAG_VER);
+
+ if (tagVer != curVer)
+ {
+ if( verbose )
+ {
+ printf("Firmware tag version [%d] is not compatible with the current Tag version [%d].\n", \
+ tagVer, curVer);
+ }
+ return -1;
+ }
+
+ if (checkChipId(xtoi(pTag->chipId), pTag->signiture_2) != 0)
+ return -1;
+
+ // check tag validate token first
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((byte *) pTag, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+
+ if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+ {
+ if( verbose )
+ printf("Illegal image ! Tag crc failed.\n");
+ return -1;
+ }
+ return 0;
+}
+
+#if (INC_NAND_FLASH_DRIVER==0)
+PFILE_TAG getTagFromPartition(int imageNumber)
+{
+ static unsigned char sectAddr1[sizeof(FILE_TAG)];
+ static unsigned char sectAddr2[sizeof(FILE_TAG)];
+ int blk = 0;
+ UINT32 crc;
+ PFILE_TAG pTag = NULL;
+ unsigned char *pBase = flash_get_memptr(0);
+ unsigned char *pSectAddr = NULL;
+
+ /* The image tag for the first image is always after the boot loader.
+ * The image tag for the second image, if it exists, is at one half
+ * of the flash size.
+ */
+ if( imageNumber == 1 )
+ {
+
+ FLASH_ADDR_INFO flash_info;
+
+ kerSysFlashAddrInfoGet(&flash_info);
+ blk = flash_get_blk((int)(pBase+flash_info.flash_rootfs_start_offset));
+ pSectAddr = sectAddr1;
+ }
+ else
+ if( imageNumber == 2 )
+ {
+ blk = flash_get_blk((int) (pBase + (flash_get_total_size() / 2)));
+ pSectAddr = sectAddr2;
+ }
+
+ if( blk )
+ {
+ memset(pSectAddr, 0x00, sizeof(FILE_TAG));
+ flash_read_buf((unsigned short) blk, 0, pSectAddr, sizeof(FILE_TAG));
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32(pSectAddr, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+ pTag = (PFILE_TAG) pSectAddr;
+ if (crc != (UINT32)(*(UINT32*)(pTag->tagValidationToken)))
+ pTag = NULL;
+ }
+
+ return( pTag );
+}
+#else
+#define tag_not_searched 0
+#define tag_not_found 1
+#define tag_found 2
+PFILE_TAG getTagFromPartition(int imageNumber)
+{
+ extern unsigned char *mem_topofmem;
+ static FILE_TAG Tag1 = {{tag_not_searched}};
+ static FILE_TAG Tag2 = {{tag_not_searched}};
+ PFILE_TAG pTag = (imageNumber == 2) ? &Tag2 : &Tag1;
+ PFILE_TAG ret = NULL;
+
+ switch( pTag->tagVersion[0] )
+ {
+ case tag_not_searched:
+ {
+ int rootfs = (imageNumber == 2) ? NP_ROOTFS_2 : NP_ROOTFS_1;
+ char fname[] = NAND_CFE_RAM_NAME;
+ int fname_actual_len = strlen(fname);
+ int fname_cmp_len = strlen(fname) - 3; /* last three are digits */
+ unsigned char *buf = (unsigned char *) mem_topofmem + 1024;
+ unsigned char *p;
+ int len = flash_get_sector_size(0);
+ int num_blks = flash_get_numsectors();
+ int i, done, start_blk, end_blk;
+ struct jffs2_raw_dirent *pdir;
+ unsigned long version = 0;
+ NVRAM_DATA nvramData;
+
+ pTag->tagVersion[0] = tag_not_found;
+ readNvramData(&nvramData);
+ validateNandPartTbl(&nvramData);
+
+ if( nvramData.ulNandPartOfsKb[rootfs] > 0 &&
+ nvramData.ulNandPartOfsKb[rootfs] < ((num_blks * len) / 1024) &&
+ nvramData.ulNandPartSizeKb[rootfs] > 0 &&
+ nvramData.ulNandPartSizeKb[rootfs] < ((num_blks * len) / 1024) )
+ {
+ const int max_not_jffs2 = 10;
+ int not_jffs2 = 0;
+
+ start_blk = nvramData.ulNandPartOfsKb[rootfs] / (len / 1024);
+ end_blk =
+ start_blk + (nvramData.ulNandPartSizeKb[rootfs] / (len / 1024));
+
+ /* Find the directory entry. */
+ for( i = start_blk, done = 0; i < end_blk && done == 0; i++ )
+ {
+ if( flash_read_buf(i, 0, buf, len) > 0 )
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) ==
+ JFFS2_NODETYPE_DIRENT &&
+ fname_actual_len == pdir->nsize &&
+ !memcmp(fname, pdir->name, fname_cmp_len) )
+ {
+ if( je32_to_cpu(pdir->version) > version )
+ {
+ if( je32_to_cpu(pdir->ino) != 0 )
+ {
+ unsigned char *seq =
+ pdir->name + fname_cmp_len;
+ pTag->imageSequence[0] = seq[0];
+ pTag->imageSequence[1] = seq[1];
+ pTag->imageSequence[2] = seq[2];
+ pTag->imageSequence[3] = '\0';
+ pTag->tagVersion[0] = tag_found;
+
+ version = je32_to_cpu(pdir->version);
+
+ /* Setting 'done = 1' assumes there is
+ * only one version of the directory
+ * entry.
+ */
+ done = 1;
+ ret = pTag;
+ break;
+ }
+ }
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ not_jffs2 = 0;
+ }
+ else
+ {
+ if( not_jffs2++ > max_not_jffs2 )
+ done = 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case tag_found:
+ ret = pTag;
+ break;
+
+ case tag_not_found:
+ ret = NULL;
+ break;
+ }
+
+ return(ret);
+}
+#endif
+
+
+int getPartitionFromTag( PFILE_TAG pTag )
+{
+ int ret = 0;
+
+ if( pTag )
+ {
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ int sequence = atoi(pTag->imageSequence);
+ int sequence1 = (pTag1) ? atoi(pTag1->imageSequence) : -1;
+ int sequence2 = (pTag2) ? atoi(pTag2->imageSequence) : -1;
+
+ if( pTag1 && sequence == sequence1 )
+ ret = 1;
+ else
+ if( pTag2 && sequence == sequence2 )
+ ret = 2;
+ }
+
+ return( ret );
+}
+
+PFILE_TAG getBootImageTag(void)
+{
+ PFILE_TAG pTag = NULL;
+
+ if( flash_get_flash_type() != FLASH_IFC_NAND )
+ {
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+
+ /* Foxconn modified end pling 10/13/2008 */
+ PFILE_TAG pTag2 = NULL;
+ // PFILE_TAG pTag2 = getTagFromPartition(2);
+ //* Foxconn modified end pling 10/13/2008 */
+
+ if( pTag1 && pTag2 )
+ {
+ /* Two images are flashed. */
+ int sequence1 = atoi(pTag1->imageSequence);
+ int sequence2 = atoi(pTag2->imageSequence);
+
+ if( bootInfo.bootPartition == BOOT_LATEST_IMAGE )
+ pTag = (sequence2 > sequence1) ? pTag2 : pTag1;
+ else /* Boot from the previous image. */
+ pTag = (sequence2 < sequence1) ? pTag2 : pTag1;
+ }
+ else
+ /* One image is flashed. */
+ pTag = (pTag2) ? pTag2 : pTag1;
+ }
+ else
+ {
+ /* TBD. Verify that linux is on the file system. */
+ /* pTag pointer is only compared to NULL for NAND flash boot. */
+ pTag = (PFILE_TAG) 1;
+ }
+
+ return( pTag );
+}
+
+static void UpdateImageSequenceNumber( char *imageSequence )
+{
+ int newImageSequence = 0;
+ PFILE_TAG pTag = getTagFromPartition(1);
+
+ if( pTag )
+ newImageSequence = atoi(pTag->imageSequence);
+
+ pTag = getTagFromPartition(2);
+ if( pTag && atoi(pTag->imageSequence) > newImageSequence )
+ newImageSequence = atoi(pTag->imageSequence);
+
+ newImageSequence++;
+ sprintf(imageSequence, "%d", newImageSequence);
+}
+
+// return -1: fail.
+// 0: OK.
+int flashImage(uint8_t *imagePtr)
+{
+ UINT32 crc;
+ FLASH_ADDR_INFO info;
+ int totalImageSize = 0;
+ int cfeSize;
+ int cfeAddr, rootfsAddr, kernelAddr;
+ int status = 0;
+ PFILE_TAG pTag = (PFILE_TAG) imagePtr;
+ NVRAM_DATA nvramData, tmpNvramData;
+
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ {
+ printf("ERROR: Image is not a valid NAND flash image.\n");
+ return -1;
+ }
+
+ // save existing NVRAM data into a local structure
+ readNvramData(&nvramData);
+
+ if( verifyTag( pTag, 1 ) == -1 )
+ return -1;
+
+ kerSysFlashAddrInfoGet( &info );
+
+ // check imageCrc
+ totalImageSize = atoi(pTag->totalImageLen);
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((imagePtr+TAG_LEN), (UINT32) totalImageSize, crc);
+
+ if (crc != (UINT32) (*(UINT32*)(pTag->imageValidationToken)))
+ {
+ printf(" Illegal image ! Image crc failed.\n");
+ return -1;
+ }
+
+ cfeSize = cfeAddr = rootfsAddr = kernelAddr = 0;
+
+ // check cfe's existence
+ cfeAddr = atoi(pTag->cfeAddress);
+ if (cfeAddr)
+ {
+ cfeSize = atoi(pTag->cfeLen);
+ if( (cfeSize <= 0) )
+ {
+ printf("Illegal cfe size [%d].\n", cfeSize );
+ return -1;
+ }
+
+ printf("\nFlashing CFE: ");
+ if ((status = kerSysBcmImageSet(cfeAddr+BOOT_OFFSET, imagePtr+TAG_LEN,
+ cfeSize, 0)) != 0)
+ {
+ printf("Failed to flash CFE. Error: %d\n", status);
+ return status;
+ }
+
+ // Check if the new image has valid NVRAM
+ if ((readNvramData(&tmpNvramData) != 0) || (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) || (BpSetVoiceBoardId(tmpNvramData.szBoardId) != BP_SUCCESS))
+ writeNvramData(&nvramData);
+ }
+
+ // check root filesystem and kernel existence
+ rootfsAddr = atoi(pTag->rootfsAddress);
+ kernelAddr = atoi(pTag->kernelAddress);
+
+ if( rootfsAddr && kernelAddr )
+ {
+ char *p;
+ unsigned char *tagFs = imagePtr;
+ unsigned int baseAddr = (unsigned int) flash_get_memptr(0);
+ unsigned int totalSize = (unsigned int) flash_get_total_size();
+ unsigned int reservedBytesAtEnd;
+ unsigned int availableSizeOneImg;
+ unsigned int reserveForTwoImages;
+ unsigned int availableSizeTwoImgs;
+ unsigned int newImgSize = atoi(pTag->rootfsLen)+atoi(pTag->kernelLen);
+ PFILE_TAG pCurTag = getBootImageTag();
+ UINT32 crc;
+ unsigned int curImgSize = 0;
+ unsigned int rootfsOffset = (unsigned int)rootfsAddr-IMAGE_BASE-TAG_LEN;
+ FLASH_ADDR_INFO flash_info;
+
+ kerSysFlashAddrInfoGet(&flash_info);
+ if( rootfsOffset < flash_info.flash_rootfs_start_offset )
+ {
+ // Increase rootfs and kernel addresses by the difference between
+ // rootfs offset and what it needs to be.
+ rootfsAddr += flash_info.flash_rootfs_start_offset - rootfsOffset;
+ kernelAddr += flash_info.flash_rootfs_start_offset - rootfsOffset;
+ sprintf(pTag->rootfsAddress,"%lu", (unsigned long) rootfsAddr);
+ sprintf(pTag->kernelAddress,"%lu", (unsigned long) kernelAddr);
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((unsigned char *)pTag,(UINT32)TAG_LEN-TOKEN_LEN,crc);
+ *(unsigned long *) &pTag->tagValidationToken[0] = crc;
+ }
+
+ rootfsAddr += BOOT_OFFSET;
+ kernelAddr += BOOT_OFFSET;
+
+ reservedBytesAtEnd = flash_get_reserved_bytes_at_end(&flash_info);
+ availableSizeOneImg = totalSize - ((unsigned int)rootfsAddr-baseAddr) -
+ reservedBytesAtEnd;
+ reserveForTwoImages =
+ (flash_info.flash_rootfs_start_offset > reservedBytesAtEnd)
+ ? flash_info.flash_rootfs_start_offset : reservedBytesAtEnd;
+ availableSizeTwoImgs = (totalSize / 2) - reserveForTwoImages;
+
+// printf("availableSizeOneImage=%dKB availableSizeTwoImgs=%dKB reserve=%dKB\n",
+// availableSizeOneImg/1024, availableSizeTwoImgs/1024, reserveForTwoImages/1024);
+
+ if( pCurTag )
+ curImgSize = atoi(pCurTag->rootfsLen) + atoi(pCurTag->kernelLen);
+
+ if( newImgSize > availableSizeOneImg)
+ {
+ printf("Illegal image size %d. Image size must not be greater "
+ "than %d.\n", newImgSize, availableSizeOneImg);
+ return -1;
+ }
+
+ // tag is alway at the sector start of fs
+ if (cfeAddr)
+ {
+ // will trash cfe memory, but cfe is already flashed
+ tagFs = imagePtr + cfeSize;
+ memcpy(tagFs, imagePtr, TAG_LEN);
+ }
+
+ // If the current image fits in half the flash space and the new
+ // image to flash also fits in half the flash space, then flash it
+ // in the partition that is not currently being used to boot from.
+ if( curImgSize <= availableSizeTwoImgs &&
+ newImgSize <= availableSizeTwoImgs &&
+ getPartitionFromTag( pCurTag ) == 1 )
+ {
+ // Update rootfsAddr to point to the second boot partition.
+ int offset = (totalSize / 2) + TAG_LEN;
+
+ sprintf(((PFILE_TAG) tagFs)->kernelAddress, "%lu",
+ (unsigned long) IMAGE_BASE + offset + (kernelAddr-rootfsAddr));
+ kernelAddr = baseAddr + offset + (kernelAddr - rootfsAddr);
+
+ sprintf(((PFILE_TAG) tagFs)->rootfsAddress, "%lu",
+ (unsigned long) IMAGE_BASE + offset);
+ rootfsAddr = baseAddr + offset;
+ }
+
+ UpdateImageSequenceNumber( ((PFILE_TAG) tagFs)->imageSequence );
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32((unsigned char *)tagFs, (UINT32)TAG_LEN-TOKEN_LEN, crc);
+ *(unsigned long *) &((PFILE_TAG) tagFs)->tagValidationToken[0] = crc;
+
+ printf("\nFlashing root file system and kernel at 0x%8.8lx: ",
+ rootfsAddr - TAG_LEN);
+ if( (status = kerSysBcmImageSet((rootfsAddr-TAG_LEN), tagFs,
+ TAG_LEN + newImgSize, 0)) != 0 )
+ {
+ printf("Failed to flash root file system. Error: %d\n", status);
+ return status;
+ }
+
+ for( p = nvramData.szBootline; p[2] != '\0'; p++ )
+ {
+ if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
+ {
+ // Change boot partition to boot from new image.
+ p[2] = BOOT_LATEST_IMAGE;
+ writeNvramData(&nvramData);
+ break;
+ }
+ }
+ }
+
+ printf(".\n*** Image flash done *** !\n");
+
+ return status;
+}
+
+static int nandUpdateImageSequenceNumber( uint8_t *imagePtr, int imageSize )
+{
+ unsigned char *buf, *p;
+ char fname[] = NAND_CFE_RAM_NAME;
+ int fname_actual_len = strlen(fname);
+ int fname_cmp_len = strlen(fname) - 3; /* last three are digits */
+ int len = flash_get_sector_size(0);
+ struct jffs2_raw_dirent *pdir;
+ unsigned long version = 0;
+ PFILE_TAG pTag1 = getTagFromPartition(1);
+ PFILE_TAG pTag2 = getTagFromPartition(2);
+ int seq = (pTag1) ? atoi(pTag1->imageSequence) : -1;
+ int seq2 = (pTag2) ? atoi(pTag2->imageSequence) : -1;
+ int ret = 0;
+
+ if( seq2 > seq )
+ seq = seq2;
+
+ if( seq != -1 )
+ {
+ int done = 0;
+
+ /* Increment the new highest sequence number. Add it to the CFE RAM
+ * file name.
+ */
+ seq++;
+
+ for(buf = imagePtr; buf < imagePtr+imageSize && done == 0; buf += len)
+ {
+ p = buf;
+ while( p < buf + len )
+ {
+ pdir = (struct jffs2_raw_dirent *) p;
+ if( je16_to_cpu(pdir->magic) == JFFS2_MAGIC_BITMASK )
+ {
+ if( je16_to_cpu(pdir->nodetype) == JFFS2_NODETYPE_DIRENT &&
+ fname_actual_len == pdir->nsize &&
+ !memcmp(fname, pdir->name, fname_cmp_len) &&
+ je32_to_cpu(pdir->version) > version &&
+ je32_to_cpu(pdir->ino) != 0 )
+ {
+ p = pdir->name + fname_cmp_len;
+ p[0] = (seq / 100) + '0';
+ p[1] = ((seq % 100) / 10) + '0';
+ p[2] = ((seq % 100) % 10) + '0';
+ p[3] = '\0';
+
+ je32_to_cpu(pdir->name_crc) = getCrc32(pdir->name,
+ (unsigned long) fname_actual_len, 0);
+
+ version = je32_to_cpu(pdir->version);
+
+ /* Setting 'done = 1' assumes there is only one version
+ * of the directory entry.
+ */
+ done = 1;
+ ret = (buf - imagePtr) / len; /* block number */
+ break;
+ }
+
+ p += (je32_to_cpu(pdir->totlen) + 0x03) & ~0x03;
+ }
+ else
+ break;
+ }
+ }
+ }
+
+ return(ret);
+}
+
+// return -1: fail.
+// 0: OK.
+int writeWholeImage(uint8_t *imagePtr, int wholeImageSize)
+{
+ UINT32 crc;
+ int status = 0;
+ int offset = 0;
+ int imageSize = wholeImageSize - TOKEN_LEN;
+ unsigned char crcBuf[CRC_LEN];
+ NVRAM_DATA nvramData, tmpNvramData;
+ WFI_TAG wfiTag;
+#if (INC_SPI_PROG_NAND==1)
+ if( flash_get_flash_type() != FLASH_IFC_NAND && wholeImageSize > FLASH_LENGTH_BOOT_ROM)
+ flash_change_flash_type(FLASH_IFC_NAND);
+#endif
+
+ // if whole image size (plus TOKEN_LEN of crc) is greater than total flash size, return error
+ if (wholeImageSize > (flash_get_total_size() + TOKEN_LEN))
+ {
+ printf("Image size too big\n");
+ return -1;
+ }
+
+ memcpy(&wfiTag, imagePtr + imageSize, sizeof(wfiTag));
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ checkChipId(wfiTag.wfiChipId, NULL) != 0 )
+ return -1;
+
+ // check tag validate token first
+ crc = CRC32_INIT_VALUE;
+ crc = getCrc32(imagePtr, (UINT32)imageSize, crc);
+ memcpy(crcBuf, imagePtr+imageSize, CRC_LEN);
+ if (memcmp(&crc, crcBuf, CRC_LEN) != 0)
+ {
+ printf("Illegal whole flash image\n");
+ return -1;
+ }
+
+ // save existing NVRAM data into a local structure
+ readNvramData(&nvramData);
+
+ if( flash_get_flash_type() == FLASH_IFC_NAND )
+ {
+ /* The CFE ROM boot loader saved the rootfs partition index at the
+ * memory location before CFE RAM load address.
+ */
+ extern unsigned char _ftext;
+
+ /* Allow addition blocks to flash cfram block that has sequence number
+ * and is flashed last.
+ */
+ const int overhead_blocks = 8;
+
+ int rootfs = (int) *(&_ftext - 1);
+ int blksize = flash_get_sector_size(0) / 1024;
+ int sectsize = flash_get_sector_size(0);
+ int i, cferam_blk, after_cferam, cferam_overhead;
+
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ ((blksize == 16 && wfiTag.wfiFlashType != WFI_NAND16_FLASH) ||
+ (blksize == 128 && wfiTag.wfiFlashType != WFI_NAND128_FLASH)) )
+ {
+ printf("\nERROR: NAND flash block size does not match image "
+ "block size\n\n");
+ return -1;
+ }
+
+ if( *(unsigned short *) imagePtr != JFFS2_MAGIC_BITMASK )
+ {
+ /* Flash block 0 (cferom). */
+ PNVRAM_DATA pnd = (PNVRAM_DATA) (imagePtr + NVRAM_DATA_OFFSET);
+ char *p;
+
+ /* Copy NVRAM data to block to be flashed so it is preserved. */
+ memcpy((unsigned char *) pnd, (unsigned char *) &nvramData,
+ sizeof(NVRAM_DATA));
+ for( p = pnd->szBootline; p[2] != '\0'; p++ )
+ {
+ if( p[0] == 'p' && p[1] == '=' && p[2] != BOOT_LATEST_IMAGE )
+ {
+ // Change boot partition to boot from new image.
+ p[2] = BOOT_LATEST_IMAGE;
+ break;
+ }
+ }
+
+ /* Recalculate the nvramData CRC. */
+ pnd->ulCheckSum = 0;
+ pnd->ulCheckSum = getCrc32((unsigned char *) pnd,
+ sizeof(NVRAM_DATA), CRC32_INIT_VALUE);
+
+ if((status = kerSysBcmImageSet(FLASH_BASE,imagePtr,sectsize,0)) != 0)
+ printf("Failed to flash block 0. Error: %d\n", status);
+ imagePtr += sectsize;
+ imageSize -= sectsize;
+ }
+
+ validateNandPartTbl(&nvramData);
+ cferam_blk = nandUpdateImageSequenceNumber(imagePtr, imageSize);
+
+ /* rootfs is the partition that the CFE RAM booted from. Write the
+ * image to the other rootfs partition.
+ */
+ if(rootfs == NP_ROOTFS_1 && nvramData.ulNandPartSizeKb[NP_ROOTFS_2]>0)
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_2] * 1024;
+ else
+ offset = nvramData.ulNandPartOfsKb[NP_ROOTFS_1] * 1024;
+
+ after_cferam = (cferam_blk + 1) * sectsize;
+ cferam_overhead = overhead_blocks * sectsize;
+
+ /* Erase block with cferam JFFS2 directory entry so if flashing this
+ * image does not finish, the partition will not be valid.
+ */
+ for( i = 0; i < (cferam_blk + 1 + overhead_blocks); i++ )
+ flash_sector_erase_int((offset / sectsize) + i);
+
+ /* Flash image after cferam directory entry. */
+ printf("\nFlashing root file system at 0x%8.8lx: ", FLASH_BASE+offset);
+ if((status = kerSysBcmImageSet(FLASH_BASE + offset + after_cferam +
+ cferam_overhead, imagePtr + after_cferam, imageSize - after_cferam,
+ 1)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+
+ /* Flash block(s) up to and including the block with cferam JFFS2
+ * directory entry.
+ */
+ if((status = kerSysBcmImageSet(FLASH_BASE + offset, imagePtr,
+ after_cferam, 0)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+ }
+ else /* NOR FLASH */
+ {
+ printf("\nFlashing root file system and kernel at 0x%8.8lx\n",
+ FLASH_BASE+offset);
+
+ if( (wfiTag.wfiVersion & WFI_ANY_VERS_MASK) == WFI_ANY_VERS &&
+ wfiTag.wfiFlashType != WFI_NOR_FLASH )
+ {
+ printf("\nERROR: Image does not support a NOR flash device.\n\n");
+ return -1;
+ }
+
+ if((status = kerSysBcmImageSet(FLASH_BASE+offset, imagePtr, imageSize,
+ 1)) != 0)
+ {
+ printf("Failed to flash whole image. Error: %d\n", status);
+ return status;
+ }
+ }
+
+ // Check if the new image has valid NVRAM
+ // Also check if the new image still supports currently configured board ID
+ if( (readNvramData(&tmpNvramData) != 0) ||
+ (BpSetBoardId(tmpNvramData.szBoardId) != BP_SUCCESS) ||
+ (BpSetVoiceBoardId(tmpNvramData.szVoiceBoardId) != BP_SUCCESS) )
+ {
+ // Don't write NVRAM area if we are flashing tiny bridge image.
+ // unlike cfe.w, the tiny bridge .w image will not have NVRAM_DATA_ID set
+ if (*(unsigned long *) &tmpNvramData == NVRAM_DATA_ID)
+ writeNvramData(&nvramData);
+ }
+
+ return status;
+}
+
+int processPrompt(PPARAMETER_SETTING promptPtr, int promptCt)
+{
+ char tmpBuf[MAX_PROMPT_LEN];
+ int i = 0;
+ int bChange = FALSE;
+
+ printf("Press: <enter> to use current value\r\n");
+ printf(" '-' to go previous parameter\r\n");
+ printf(" '.' to clear the current value\r\n");
+ printf(" 'x' to exit this command\r\n");
+
+ memset(tmpBuf, 0, MAX_PROMPT_LEN);
+ while (i < promptCt)
+ {
+ if( (promptPtr+i)->enabled == FALSE )
+ {
+ if( tmpBuf[0] == '-' )
+ {
+ if( i > 0 )
+ {
+ i--;
+ continue;
+ }
+ }
+ else
+ {
+ i++;
+ continue;
+ }
+ }
+
+ if (strlen((promptPtr+i)->parameter) > 0)
+ printf("%s %s ", (promptPtr+i)->promptName, (promptPtr+i)->parameter);
+ else
+ printf("%s %s", (promptPtr+i)->promptName, (promptPtr+i)->parameter);
+
+ memset(tmpBuf, 0, MAX_PROMPT_LEN);
+ console_readline ("", tmpBuf, (promptPtr+i)->maxValueLength + 1);
+
+ switch (tmpBuf[0])
+ {
+ case '-': // go back one parameter
+ if (i > 0)
+ i--;
+ break;
+ case 'x': // get out the b command
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func((promptPtr+i)->parameter))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ i = promptCt;
+ break;
+ case '.': // clear the current parameter and advance
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func(""))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN);
+ i++;
+ bChange = TRUE;
+ break;
+ case 0: // no input; use default if it is OK
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func((promptPtr+i)->parameter))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ i++;
+ break;
+ default: // new parameter
+ if ((promptPtr+i)->func != 0) // validate function is supplied, do a check
+ {
+ if ((promptPtr+i)->func(tmpBuf))
+ {
+ printf("\n%s; Try again!\n", (promptPtr+i)->errorPrompt);
+ break;
+ }
+ }
+ memset((promptPtr+i)->parameter, 0, MAX_PROMPT_LEN);
+ memcpy((promptPtr+i)->parameter, tmpBuf, strlen(tmpBuf));
+ i++;
+ bChange = TRUE;
+ }
+ }
+
+ return bChange;
+
+} // processPrompt
+
+// write the nvramData struct to nvram after CRC is calculated
+void writeNvramData(PNVRAM_DATA pNvramData)
+{
+ UINT32 crc = CRC32_INIT_VALUE;
+
+ pNvramData->ulCheckSum = 0;
+ crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc);
+ pNvramData->ulCheckSum = crc;
+ kerSysNvRamSet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0);
+}
+
+// read the nvramData struct from nvram
+// return -1: crc fail, 0 ok
+int readNvramData(PNVRAM_DATA pNvramData)
+{
+ UINT32 crc = CRC32_INIT_VALUE, savedCrc;
+
+ kerSysNvRamGet((unsigned char *)pNvramData, sizeof(NVRAM_DATA), 0);
+ savedCrc = pNvramData->ulCheckSum;
+ pNvramData->ulCheckSum = 0;
+ crc = getCrc32((unsigned char *)pNvramData, sizeof(NVRAM_DATA), crc);
+ if (savedCrc != crc)
+ return -1;
+
+ return 0;
+}
+
+static void convertBootInfo(void)
+{
+ char *x;
+
+ memset(&bootInfo, 0, sizeof(BOOT_INFO));
+ strcpy(bootInfo.boardIp, gBootParam[PARAM_IDX_BOARD_IPADDR].parameter);
+
+ if ((x = strchr(bootInfo.boardIp, ':'))) // has mask
+ {
+ *x = '\0';
+ convertMaskStr((x+1), bootInfo.boardMask);
+ }
+ strcpy(bootInfo.hostIp, gBootParam[PARAM_IDX_HOST_IPADDR].parameter);
+ if ((x = strchr(bootInfo.hostIp, ':'))) // ignore host mask
+ *x = '\0';
+ strcpy(bootInfo.gatewayIp, gBootParam[PARAM_IDX_GW_IPADDR].parameter);
+ if ((x = strchr(bootInfo.gatewayIp, ':'))) // ignore gw mask
+ *x = '\0';
+ bootInfo.runFrom = gBootParam[PARAM_IDX_RUN_FROM].parameter[0];
+ strcpy(bootInfo.hostFileName, gBootParam[PARAM_IDX_RUN_FILENAME].parameter);
+ strcpy(bootInfo.flashFileName, gBootParam[PARAM_IDX_FLASH_FILENAME].parameter);
+ bootInfo.bootDelay = (int)(gBootParam[PARAM_IDX_BOOT_DELAY].parameter[0] - '0');
+ bootInfo.bootPartition = gBootParam[PARAM_IDX_BOOT_IMAGE].parameter[0];
+}
+
+void getBootLine(void)
+{
+ int i;
+ char *curPtr;
+ char *dPtr;
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ if ((nvramData.szBootline[0] == (char)0xff) ||
+ (nvramData.szBootline[0] == (char)0))
+ {
+ setDefaultBootline();
+ return;
+ }
+
+ curPtr = nvramData.szBootline;
+ for (i = 0; (i < gNumBootParams) && (curPtr != 0); i++)
+ {
+ curPtr = strchr(curPtr, '=');
+ if (curPtr) // found '=' and get the param.
+ {
+ dPtr = strchr(curPtr, ' '); // find param. deliminator ' '
+ memset(gBootParam[i].parameter, 0, MAX_PROMPT_LEN);
+ memcpy(gBootParam[i].parameter, curPtr+1, dPtr-curPtr-1);
+ // move to next param.
+ curPtr = dPtr;
+ }
+ } // for loop
+
+ if (i < gNumBootParams) {
+ setDefaultBootline();
+ return;
+ }
+
+ convertBootInfo();
+}
+
+// print the bootline and board parameter info and fill in the struct for later use
+//
+int printSysInfo(void)
+{
+ int i;
+ ETHERNET_MAC_INFO EnetInfos[BP_MAX_ENET_MACS];
+
+ // display the bootline info
+
+ if( getTagFromPartition(1) == NULL || getTagFromPartition(2) == NULL )
+ gBootParam[PARAM_IDX_BOOT_IMAGE].enabled = FALSE;
+
+ for (i = 0; i < gNumBootParams; i++)
+ if( gBootParam[i].enabled )
+ printf("%s %s \n", gBootParam[i].promptName, gBootParam[i].parameter);
+
+ // display the board param
+ displayBoardParam();
+
+ if( BpGetEthernetMacInfo( EnetInfos, BP_MAX_ENET_MACS ) == BP_SUCCESS )
+ {
+ // Here we should print whether EMAC1 or EMAC2 is selected
+ }
+
+ printf("\n");
+
+ return 0;
+}
+
+
+//**************************************************************************
+// Function Name: changeBootLine
+// Description : Use vxWorks bootrom style parameter input method:
+// Press <enter> to use default, '-' to go to previous parameter
+// Note: Parameter is set to current value in the menu.
+// Returns : None.
+//**************************************************************************
+int changeBootLine(void)
+{
+ int i;
+ char boardIpSaved[BOOT_IP_LEN];
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+
+ strcpy(boardIpSaved, bootInfo.boardIp);
+
+ if (processPrompt(gBootParam, gNumBootParams))
+ {
+ char *blPtr = nvramData.szBootline;
+ int paramLen;
+
+ memset(blPtr, 0, NVRAM_BOOTLINE_LEN);
+ for (i = 0; i < gNumBootParams; i++)
+ {
+ memcpy(blPtr, gBootParam[i].promptDefine, PROMPT_DEFINE_LEN);
+ blPtr += PROMPT_DEFINE_LEN;
+ paramLen = strlen(gBootParam[i].parameter);
+ memcpy(blPtr, gBootParam[i].parameter, paramLen);
+ blPtr += paramLen;
+ if (!(gBootParam[i].parameter[0] == ' '))
+ {
+ memcpy(blPtr, " ", 1);
+ blPtr += 1;
+ }
+ }
+ writeNvramData(&nvramData);
+ }
+
+ getBootLine();
+
+ // if board ip differs, do enet init
+ if (strcmp(boardIpSaved, bootInfo.boardIp) != 0)
+ enet_init();
+
+ return 0;
+
+}
+
+void setDefaultBootline(void)
+{
+ char boardIpSaved[BOOT_IP_LEN];
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+ strcpy(boardIpSaved, bootInfo.boardIp);
+
+ memset(nvramData.szBootline, 0, NVRAM_BOOTLINE_LEN);
+ strncpy(nvramData.szBootline, DEFAULT_BOOTLINE, strlen(DEFAULT_BOOTLINE));
+ printf("Use default boot line parameters: %s\n", DEFAULT_BOOTLINE);
+ writeNvramData(&nvramData);
+
+ getBootLine();
+
+ // if board ip differs, do enet init
+ if (strcmp(boardIpSaved, bootInfo.boardIp) != 0)
+ enet_init();
+}
+
+//**************************************************************************
+// Function Name: changeAfeId
+// Description : Use vxWorks bootrom style parameter input method:
+// Press <enter> to use default, '-' to go to previous parameter
+// Note: Parameter is set to current value in the menu.
+// Returns : None.
+//**************************************************************************
+static void hex2Str(unsigned long num, char *str)
+{
+ static const char hextable[16] = "0123456789ABCDEF";
+ unsigned long i, n;
+ str[0] = '0';
+ str[1] = 'x';
+ if (0 == num) {
+ str[2] = '0';
+ str[3] = 0;
+ return;
+ }
+ str +=2;
+ n = num >> 28;
+ i = 0;
+ while (0 == n) {
+ num <<= 4;
+ n = num >> 28;
+ i++;
+ }
+ for (; i < 8; i++) {
+ *str++ = hextable[num >> 28];
+ num <<= 4;
+ }
+ *str = 0;
+}
+
+int changeAfeId(void)
+{
+ NVRAM_DATA nvramData;
+
+ readNvramData(&nvramData);
+ hex2Str(nvramData.afeId[0], gAfeId[0].parameter);
+ hex2Str(nvramData.afeId[1], gAfeId[1].parameter);
+ if (processPrompt(gAfeId, gAfeIdParams))
+ {
+ nvramData.afeId[0] = lib_atoi(gAfeId[0].parameter);
+ nvramData.afeId[1] = lib_atoi(gAfeId[1].parameter);
+ writeNvramData(&nvramData);
+ }
+ return 0;
+}