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