1 /*---------------------------------------------------------------------------*
2 Project: boot1 system file generator
3 File: makebsf.c
4
5 Copyright 2010 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: makebsf.c $
14 $NoKeywords: $
15 *---------------------------------------------------------------------------*/
16
17 //#include <getopt.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22
23 //#include <types.h>
24
25 #include "bootosBootBlock.h"
26
27 #define BSFFILE "ppc.bsf"
28 #define HEADERSIZE 32
29 #define MAXSIZE (1024*1024)
30
31 #define REV32(x) ( (((x) & 0x000000ff) << 24) \
32 | ( ((x) & 0x0000ff00) << 8) \
33 | ( ((x) & 0x00ff0000) >> 8) \
34 | ( ((x) & 0xff000000) >> 24) )
35
36 #define RoundUp32(n) (((u32)(n) + 31) & ~((u32)31))
37
38 //#define PARSE_ONLY
39 //#define ENABLE_DEBUG_MESSAGE
40
41 #define ENV_VAR_STICKY_REGISTER "_CCRSYSCFG1"
42 #define ENV_VAR_IOS_DEBUG_STARTUP "IOS_DEBUG_STARTUP"
43
44 char* AppName;
45 static u8 Quiet = 0;
46
usage(int err)47 static void usage(int err)
48 {
49 printf("usage: %s [args]\n", AppName);
50 printf(" -b bs0_file # \n");
51 printf(" -p <process1,process2,...> # process file list\n");
52 printf(" -a <address1,address2,...> # address list\n");
53 printf(" -o output # output file\n");
54 printf(" -i platform_info_paddr # physical address of platform information\n");
55 printf(" -j package_info_paddr # physical address of package information\n");
56 printf(" -f bsf flags # flags in boot block header\n");
57 printf(" -q # quiet\n");
58 exit(err);
59 }
60
61 /*---------------------------------------------------------------------------*
62 Name: MakeBsf
63
64 Description: TBD
65
66 Arguments: TBD
67
68 Returns: pointer to RAM image
69 *---------------------------------------------------------------------------*/
MakeBsf(u32 num,u32 * addresslist,u32 * lengthlist,u32 platform_info_paddr,u32 package_info_paddr,u32 flags,u32 ccrsyscfg1,u32 * size)70 static void* MakeBsf(u32 num, u32* addresslist, u32* lengthlist,
71 u32 platform_info_paddr, u32 package_info_paddr, u32 flags, u32 ccrsyscfg1, u32* size)
72 {
73 u8* image;
74 bootosBootBlockHeader* header;
75 bootosBootBlockDataInfo* infos;
76 u32 i;
77
78 // Initializing output buffer
79 image = (u8 *)malloc(MAXSIZE);
80 if (image == NULL)
81 {
82 fprintf(stderr, "%s: unable to allocate sufficient memory\n", AppName);
83 return NULL;
84 }
85 memset(image, 0, MAXSIZE);
86
87 header = (bootosBootBlockHeader*)image;
88 header->magic = REV32(BOOTOS_BOOT_BLOCK_MAGIC);
89 header->num = REV32(num);
90 header->platform_info_paddr = REV32(platform_info_paddr);
91 header->package_info_paddr = REV32(package_info_paddr);
92 header->flags = REV32(flags);
93 header->ccrsyscfg1 = REV32(ccrsyscfg1);
94
95 infos = (bootosBootBlockDataInfo*)(image + sizeof(bootosBootBlockHeader));
96 for(i = 0; i < num; i++)
97 {
98 infos->address = REV32(addresslist[i]);
99 infos->length = REV32(lengthlist[i]);
100 infos++;
101 }
102
103 *size = RoundUp32(sizeof(bootosBootBlockHeader) + sizeof(bootosBootBlockDataInfo)*num);
104
105 return image;
106 }
107
ConvertToUnixFmt(char * fmt)108 void ConvertToUnixFmt(char* fmt)
109 {
110 if (fmt == NULL)
111 return;
112
113 if ( (*fmt == '/') && (*(fmt + 1) == '/') )
114 {
115 *fmt = *(fmt + 2);
116 *(fmt + 1) = ':';
117
118 fmt += 3;
119 while (*fmt != '\0')
120 {
121 *(fmt - 1) = *fmt;
122 fmt++;
123 }
124
125 *(fmt - 1) = '\0';
126 }
127 }
128
CheckStickyRegisterEnvVar(u32 * ccrsyscfg1)129 u32 CheckStickyRegisterEnvVar (u32 *ccrsyscfg1)
130 {
131 u32 flags = 0;
132 u32 args = 0;
133 char *sys_cfg;
134 char *p = NULL;
135
136 sys_cfg = getenv(ENV_VAR_STICKY_REGISTER);
137 if (NULL != sys_cfg)
138 {
139 /* Allows sticky register to be set arbitrarily */
140 errno = 0;
141 args |= strtoul(sys_cfg, &p, 16);
142 flags |= BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG;
143 if (*p != '\0')
144 {
145 printf("makebsf: %s could not be converted as hexadecimal number: '%s' \n", ENV_VAR_STICKY_REGISTER, sys_cfg);
146 args = 0;
147 flags = 0;
148 }
149 if (errno != 0)
150 {
151 printf("makebsf: %s could not be converted as hexadecimal number: errno %d\n", ENV_VAR_STICKY_REGISTER, errno);
152 args = 0;
153 flags = 0;
154 }
155 }
156
157 sys_cfg = getenv(ENV_VAR_IOS_DEBUG_STARTUP);
158 if (NULL != sys_cfg && *sys_cfg != '\0' && *sys_cfg != '0')
159 {
160 /* Convenience environment variable */
161 /* IOS_STICKY_ENTRY_ARG_RUNTIME_DEBUG_ON = 0x80000000 (can't include iostypes.h for now) */
162 args |= 0x80000000;
163 flags |= BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG;
164 }
165
166 if (ccrsyscfg1)
167 *ccrsyscfg1 = args;
168
169 return flags;
170 }
171
main(int argc,char ** argv)172 int main(int argc, char **argv)
173 {
174 u32 num = 0;
175 u32 addressList[256];
176 u32 lengthList [256];
177
178 u32 addressNum = 0;
179 u32 lengthNum = 0;
180
181 u32 platform_info_paddr = 0;
182 u32 package_info_paddr = 0;
183 u32 flags = 0;
184 u32 ccrsyscfg1 = 0;
185
186 char* outName = BSFFILE;
187
188 u32 size = 0;
189
190 char* token = NULL;
191 char* optarg = NULL;
192 char* cur = NULL;
193 FILE* fp = NULL;
194 s32 errFlg = 0;
195 s32 c;
196 s32 argIdx = 1;
197 void* image;
198 FILE* file;
199
200 memset(addressList, 0, sizeof(u32)*256);
201 memset(lengthList, 0, sizeof(u32)*256);
202
203 AppName = argv[0];
204
205 while(argIdx < argc)
206 {
207 if(argc == 1)
208 {
209 c = '?';
210 }
211 else
212 {
213 cur = argv[argIdx++];
214
215 if((strlen(cur) == 2) && (cur[0] == '-'))
216 {
217 c = cur[1];
218 if(argIdx < argc && ((argv[argIdx])[0] != '-') )
219 {
220 optarg = argv[argIdx++];
221 }
222 }
223 else
224 {
225 c = '?';
226 }
227 }
228
229 switch (c)
230 {
231 case 'q':
232 Quiet = 1;
233 break;
234
235 case 'o':
236 outName = optarg;
237 break;
238
239 case 'i':
240 platform_info_paddr = strtoul(optarg, NULL, 0);
241 if (!Quiet)
242 printf("platform info address: 0x%08x\n", platform_info_paddr);
243 break;
244
245 case 'j':
246 package_info_paddr = strtoul(optarg, NULL, 0);
247 if (!Quiet)
248 printf("package info address: 0x%08x\n", package_info_paddr);
249 break;
250
251 case 'p':
252 token = strtok(optarg, ",");
253 while (token)
254 {
255 ConvertToUnixFmt(token);
256 if (!Quiet)
257 printf("process %d: %s ", lengthNum+1, token);
258 fp = fopen(token, "rb");
259 if ( fp == NULL )
260 {
261 fprintf(stderr, "unable to open %s\n", token);
262 errFlg++;
263 break;
264 }
265 fseek(fp, 0, SEEK_END);
266 lengthList[lengthNum] = ftell(fp);
267 fclose(fp);
268 if (!Quiet)
269 printf("(0x%08x)\n", lengthList[lengthNum]);
270 lengthNum++;
271 token = strtok(NULL, ",");
272 }
273 break;
274
275 case 'a':
276 token = strtok(optarg, ",");
277 while (token)
278 {
279 addressList[addressNum] = strtoul(token, NULL, 0);
280 if (!Quiet)
281 printf("address %d: 0x%08x\n", addressNum+1, addressList[addressNum]);
282 addressNum++;
283 token = strtok(NULL, ",");
284 }
285 break;
286
287 case 'f':
288 token = strtok(optarg, ",");
289 if (token)
290 {
291 flags = strtoul(token, NULL, 0);
292 if (!Quiet)
293 printf("flags 0x%08x\n", flags);
294 }
295 break;
296
297 case 'h':
298 usage(0);
299 break;
300
301 default:
302 fprintf(stderr, "unknown option %c\n", c);
303 errFlg++;
304 break;
305 }
306 }
307
308 if (!Quiet)
309 {
310 printf("EVL0 system file generator. Copyright 2009 Nintendo.\n");
311 printf("Built : %s %s\n", __DATE__, __TIME__);
312 }
313
314 if ((addressNum != lengthNum) || !outName || errFlg)
315 {
316 fprintf(stderr, "invalid argument\n");
317 usage(EXIT_FAILURE);
318 }
319
320 flags |= CheckStickyRegisterEnvVar (&ccrsyscfg1); // keep values passed from bootrun
321
322 if (flags & BOOTOS_BOOT_BLOCK_PASS_OPTS_VIA_CFG_REG) // enable boot1 1.9.5+ to initialize sticky register
323 {
324 if (ccrsyscfg1 & 0x80000000)
325 {
326 printf ("Halting during IOS startup... Please use JTAG to continue\n");
327 }
328 else if (ccrsyscfg1 & 0x7FFFFFFF)
329 {
330 printf ("Initializing sticky register using 0x%08x\n", ccrsyscfg1);
331 }
332 }
333
334 ConvertToUnixFmt(outName);
335
336 image = MakeBsf(addressNum, addressList, lengthList, platform_info_paddr, package_info_paddr, flags, ccrsyscfg1, &size);
337 if (image == NULL)
338 {
339 exit(EXIT_FAILURE);
340 }
341
342 #ifndef PARSE_ONLY
343 // Blast out the entire image to the file
344 file = fopen(outName, "wb");
345 if (file == NULL)
346 {
347 fprintf(stderr, "%s: unable to open img output file\n", AppName);
348 exit(EXIT_FAILURE);
349 }
350 if (fwrite(image, 1, size, file) != size)
351 {
352 fprintf(stderr, "%s: failed to write img output file\n", AppName);
353 exit(EXIT_FAILURE);
354 }
355 fclose(file);
356 #endif
357
358 if (!Quiet)
359 printf("Generated %s (%d bytes)\n", outName, size);
360
361 free(image);
362
363 return 0;
364 }
365