/*---------------------------------------------------------------------------* Project: boot1 system file generator File: makebsf.c Copyright 2010 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: makebsf.c $ $NoKeywords: $ *---------------------------------------------------------------------------*/ //#include #include #include #include #include //#include #include "bootosBootBlock.h" #define BSFFILE "ppc.bsf" #define HEADERSIZE 32 #define MAXSIZE (1024*1024) #define REV32(x) ( (((x) & 0x000000ff) << 24) \ | ( ((x) & 0x0000ff00) << 8) \ | ( ((x) & 0x00ff0000) >> 8) \ | ( ((x) & 0xff000000) >> 24) ) #define RoundUp32(n) (((u32)(n) + 31) & ~((u32)31)) //#define PARSE_ONLY //#define ENABLE_DEBUG_MESSAGE #define ENV_VAR_STICKY_REGISTER "_CCRSYSCFG1" #define ENV_VAR_IOS_DEBUG_STARTUP "IOS_DEBUG_STARTUP" char* AppName; static u8 Quiet = 0; static void usage(int err) { printf("usage: %s [args]\n", AppName); printf(" -b bs0_file # \n"); printf(" -p # process file list\n"); printf(" -a # address list\n"); printf(" -o output # output file\n"); printf(" -i platform_info_paddr # physical address of platform information\n"); printf(" -j package_info_paddr # physical address of package information\n"); printf(" -f bsf flags # flags in boot block header\n"); printf(" -q # quiet\n"); exit(err); } /*---------------------------------------------------------------------------* Name: MakeBsf Description: TBD Arguments: TBD Returns: pointer to RAM image *---------------------------------------------------------------------------*/ static void* MakeBsf(u32 num, u32* addresslist, u32* lengthlist, u32 platform_info_paddr, u32 package_info_paddr, u32 flags, u32 ccrsyscfg1, u32* size) { u8* image; bootosBootBlockHeader* header; bootosBootBlockDataInfo* infos; u32 i; // Initializing output buffer image = (u8 *)malloc(MAXSIZE); if (image == NULL) { fprintf(stderr, "%s: unable to allocate sufficient memory\n", AppName); return NULL; } memset(image, 0, MAXSIZE); header = (bootosBootBlockHeader*)image; header->magic = REV32(BOOTOS_BOOT_BLOCK_MAGIC); header->num = REV32(num); header->platform_info_paddr = REV32(platform_info_paddr); header->package_info_paddr = REV32(package_info_paddr); header->flags = REV32(flags); header->ccrsyscfg1 = REV32(ccrsyscfg1); infos = (bootosBootBlockDataInfo*)(image + sizeof(bootosBootBlockHeader)); for(i = 0; i < num; i++) { infos->address = REV32(addresslist[i]); infos->length = REV32(lengthlist[i]); infos++; } *size = RoundUp32(sizeof(bootosBootBlockHeader) + sizeof(bootosBootBlockDataInfo)*num); return image; } void ConvertToUnixFmt(char* fmt) { if (fmt == NULL) return; if ( (*fmt == '/') && (*(fmt + 1) == '/') ) { *fmt = *(fmt + 2); *(fmt + 1) = ':'; fmt += 3; while (*fmt != '\0') { *(fmt - 1) = *fmt; fmt++; } *(fmt - 1) = '\0'; } } u32 CheckStickyRegisterEnvVar (u32 *ccrsyscfg1) { u32 flags = 0; u32 args = 0; char *sys_cfg; char *p = NULL; sys_cfg = getenv(ENV_VAR_STICKY_REGISTER); if (NULL != sys_cfg) { /* Allows sticky register to be set arbitrarily */ errno = 0; args |= strtoul(sys_cfg, &p, 16); flags |= BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG; if (*p != '\0') { printf("makebsf: %s could not be converted as hexadecimal number: '%s' \n", ENV_VAR_STICKY_REGISTER, sys_cfg); args = 0; flags = 0; } if (errno != 0) { printf("makebsf: %s could not be converted as hexadecimal number: errno %d\n", ENV_VAR_STICKY_REGISTER, errno); args = 0; flags = 0; } } sys_cfg = getenv(ENV_VAR_IOS_DEBUG_STARTUP); if (NULL != sys_cfg && *sys_cfg != '\0' && *sys_cfg != '0') { /* Convenience environment variable */ /* IOS_STICKY_ENTRY_ARG_RUNTIME_DEBUG_ON = 0x80000000 (can't include iostypes.h for now) */ args |= 0x80000000; flags |= BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG; } if (ccrsyscfg1) *ccrsyscfg1 = args; return flags; } int main(int argc, char **argv) { u32 num = 0; u32 addressList[256]; u32 lengthList [256]; u32 addressNum = 0; u32 lengthNum = 0; u32 platform_info_paddr = 0; u32 package_info_paddr = 0; u32 flags = 0; u32 ccrsyscfg1 = 0; char* outName = BSFFILE; u32 size = 0; char* token = NULL; char* optarg = NULL; char* cur = NULL; FILE* fp = NULL; s32 errFlg = 0; s32 c; s32 argIdx = 1; void* image; FILE* file; memset(addressList, 0, sizeof(u32)*256); memset(lengthList, 0, sizeof(u32)*256); AppName = argv[0]; while(argIdx < argc) { if(argc == 1) { c = '?'; } else { cur = argv[argIdx++]; if((strlen(cur) == 2) && (cur[0] == '-')) { c = cur[1]; if(argIdx < argc && ((argv[argIdx])[0] != '-') ) { optarg = argv[argIdx++]; } } else { c = '?'; } } switch (c) { case 'q': Quiet = 1; break; case 'o': outName = optarg; break; case 'i': platform_info_paddr = strtoul(optarg, NULL, 0); if (!Quiet) printf("platform info address: 0x%08x\n", platform_info_paddr); break; case 'j': package_info_paddr = strtoul(optarg, NULL, 0); if (!Quiet) printf("package info address: 0x%08x\n", package_info_paddr); break; case 'p': token = strtok(optarg, ","); while (token) { ConvertToUnixFmt(token); if (!Quiet) printf("process %d: %s ", lengthNum+1, token); fp = fopen(token, "rb"); if ( fp == NULL ) { fprintf(stderr, "unable to open %s\n", token); errFlg++; break; } fseek(fp, 0, SEEK_END); lengthList[lengthNum] = ftell(fp); fclose(fp); if (!Quiet) printf("(0x%08x)\n", lengthList[lengthNum]); lengthNum++; token = strtok(NULL, ","); } break; case 'a': token = strtok(optarg, ","); while (token) { addressList[addressNum] = strtoul(token, NULL, 0); if (!Quiet) printf("address %d: 0x%08x\n", addressNum+1, addressList[addressNum]); addressNum++; token = strtok(NULL, ","); } break; case 'f': token = strtok(optarg, ","); if (token) { flags = strtoul(token, NULL, 0); if (!Quiet) printf("flags 0x%08x\n", flags); } break; case 'h': usage(0); break; default: fprintf(stderr, "unknown option %c\n", c); errFlg++; break; } } if (!Quiet) { printf("EVL0 system file generator. Copyright 2009 Nintendo.\n"); printf("Built : %s %s\n", __DATE__, __TIME__); } if ((addressNum != lengthNum) || !outName || errFlg) { fprintf(stderr, "invalid argument\n"); usage(EXIT_FAILURE); } flags |= CheckStickyRegisterEnvVar (&ccrsyscfg1); // keep values passed from bootrun if (flags & BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG) // enable boot1 1.9.5+ to initialize sticky register { if (ccrsyscfg1 & 0x80000000) { printf ("Halting during IOS startup... Please use JTAG to continue\n"); } else if (ccrsyscfg1 & 0x7FFFFFFF) { printf ("Initializing sticky register using 0x%08x\n", ccrsyscfg1); } } ConvertToUnixFmt(outName); image = MakeBsf(addressNum, addressList, lengthList, platform_info_paddr, package_info_paddr, flags, ccrsyscfg1, &size); if (image == NULL) { exit(EXIT_FAILURE); } #ifndef PARSE_ONLY // Blast out the entire image to the file file = fopen(outName, "wb"); if (file == NULL) { fprintf(stderr, "%s: unable to open img output file\n", AppName); exit(EXIT_FAILURE); } if (fwrite(image, 1, size, file) != size) { fprintf(stderr, "%s: failed to write img output file\n", AppName); exit(EXIT_FAILURE); } fclose(file); #endif if (!Quiet) printf("Generated %s (%d bytes)\n", outName, size); free(image); return 0; }