1 /*---------------------------------------------------------------------------*
2 Project: NitroSDK - CRYPTO - demos
3 File: main.c
4
5 Copyright 2008-2009 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 $Date::$
14 $Rev:$
15 $Author:$
16 *---------------------------------------------------------------------------*/
17 /*---------------------------------------------------------------------------*
18 This demo confirms that the CRYPTO library's RSA encryption functions operate properly
19 *---------------------------------------------------------------------------*/
20
21 #include <nitro.h>
22 #include <nitro/crypto.h>
23 #include <nitro/std.h>
24 #include <string.h>
25
26 //#define PRINT_ALLOCATION
27 #define PUBKEY_USE_MODULOUS_ONLY 0
28
29 static void InitializeAllocateSystem(void);
30 static void VBlankIntr(void);
31 static void DisplayInit(void);
32 static void FillScreen(u16 col);
33 static BOOL RsaTest(void);
34 static u32 GetStringLength(char* str);
35 static void PrintBinary(u8* ptr, int len);
36
37 /*---------------------------------------------------------------------------*
38 Variable Definitions
39 *---------------------------------------------------------------------------*/
40
41 #ifdef PRINT_ALLOCATION
42 static u32 total_allocated_size = 0;
43 #endif
44
45 #if (PUBKEY_USE_MODULOUS_ONLY == 0)
46 static const unsigned char rsa512_pub[]={
47 0x30, 0x5C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05,
48 0x00, 0x03, 0x4B, 0x00, 0x30, 0x48, 0x02, 0x41, 0x00, 0xAA, 0x3D, 0x39, 0x23, 0x81, 0x1E, 0x04,
49 0xDB, 0x25, 0x91, 0xE4, 0x15, 0xA5, 0x3A, 0x9A, 0xCF, 0x64, 0x7F, 0x2F, 0xD6, 0x03, 0xB1, 0x6C,
50 0xA4, 0x1E, 0x6A, 0x4D, 0x7C, 0x9A, 0x02, 0x7D, 0x9A, 0x8E, 0xF9, 0x8F, 0x61, 0x9C, 0x0E, 0x42,
51 0x49, 0x58, 0xBB, 0x96, 0xB1, 0x1F, 0x7C, 0xCA, 0x7B, 0x2A, 0x75, 0x3A, 0x6C, 0x82, 0x4F, 0xF9,
52 0xF5, 0xB2, 0x11, 0xB7, 0xC4, 0xCC, 0xF9, 0x6D, 0xE7, 0x02, 0x03, 0x01, 0x00, 0x01
53 };
54 static const int rsa512_pub_len = 0x5E;
55
56 static const unsigned char rsa512_sec[]={
57 0x30, 0x82, 0x01, 0x3A, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xAA, 0x3D, 0x39, 0x23, 0x81, 0x1E,
58 0x04, 0xDB, 0x25, 0x91, 0xE4, 0x15, 0xA5, 0x3A, 0x9A, 0xCF, 0x64, 0x7F, 0x2F, 0xD6, 0x03, 0xB1,
59 0x6C, 0xA4, 0x1E, 0x6A, 0x4D, 0x7C, 0x9A, 0x02, 0x7D, 0x9A, 0x8E, 0xF9, 0x8F, 0x61, 0x9C, 0x0E,
60 0x42, 0x49, 0x58, 0xBB, 0x96, 0xB1, 0x1F, 0x7C, 0xCA, 0x7B, 0x2A, 0x75, 0x3A, 0x6C, 0x82, 0x4F,
61 0xF9, 0xF5, 0xB2, 0x11, 0xB7, 0xC4, 0xCC, 0xF9, 0x6D, 0xE7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
62 0x40, 0x75, 0x8E, 0xA1, 0x8E, 0x6A, 0xF3, 0x17, 0xD7, 0x5D, 0x32, 0x49, 0x96, 0xC8, 0xEA, 0x97,
63 0x4C, 0xEF, 0xD1, 0x04, 0x6F, 0x7D, 0x4D, 0x60, 0x00, 0x55, 0x20, 0x83, 0x31, 0xB0, 0x08, 0x58,
64 0x42, 0xEA, 0x75, 0x28, 0xB7, 0xB7, 0x44, 0xA7, 0x03, 0xF8, 0xEC, 0x80, 0x67, 0xD2, 0xF5, 0x44,
65 0x14, 0x77, 0x7D, 0x3F, 0xE7, 0x12, 0x2C, 0xAB, 0xE8, 0xBA, 0x52, 0x0E, 0xD5, 0x1F, 0xE5, 0xC1,
66 0x81, 0x02, 0x21, 0x00, 0xD1, 0xE4, 0x7B, 0xDE, 0x44, 0xE2, 0x4E, 0x03, 0xE5, 0x74, 0xCD, 0x89,
67 0xFD, 0x15, 0x8A, 0xD8, 0xAE, 0xF4, 0x67, 0x87, 0xCF, 0x65, 0x52, 0x3C, 0x23, 0x13, 0x2B, 0xE9,
68 0x97, 0x33, 0x26, 0x69, 0x02, 0x21, 0x00, 0xCF, 0xA2, 0xCA, 0xF1, 0x9F, 0xB0, 0x49, 0x1E, 0x4E,
69 0x64, 0x5F, 0xC7, 0x21, 0xE0, 0x71, 0x7E, 0x93, 0x7A, 0x5B, 0x20, 0xB1, 0x89, 0xAF, 0xF9, 0xC8,
70 0x96, 0x23, 0xBB, 0x72, 0xFC, 0x87, 0xCF, 0x02, 0x21, 0x00, 0xA8, 0xF7, 0x3C, 0x58, 0x44, 0x2F,
71 0xC2, 0x0A, 0x14, 0xEF, 0xA0, 0x7F, 0x13, 0x04, 0x02, 0x90, 0x48, 0xD7, 0x6B, 0x78, 0xC3, 0x16,
72 0x97, 0xCA, 0xDD, 0x99, 0x93, 0x62, 0x2A, 0x5B, 0xFC, 0xF1, 0x02, 0x20, 0x11, 0x44, 0x4E, 0x70,
73 0x2D, 0x81, 0x71, 0x73, 0x2D, 0xBD, 0xB7, 0x21, 0x4E, 0x35, 0xE5, 0xFA, 0x4A, 0xB5, 0x60, 0x22,
74 0xA5, 0xE0, 0xF7, 0x5B, 0x64, 0x4C, 0xE8, 0x07, 0xCC, 0x96, 0x27, 0x8D, 0x02, 0x20, 0x42, 0xEA,
75 0x98, 0x73, 0x96, 0x3E, 0xAC, 0x03, 0x3B, 0x19, 0xD0, 0xB7, 0x29, 0x11, 0x94, 0x25, 0x0E, 0x98,
76 0xC4, 0x7C, 0xA5, 0x95, 0x64, 0x02, 0x34, 0xB8, 0x4B, 0x66, 0x1E, 0x7B, 0x99, 0xB4
77 };
78 static const int rsa512_sec_len = 0x13E;
79 #else
80 //Modulus only
81 static const unsigned char rsa512_pub[]={
82 0x30, 0x48, 0x02, 0x41, 0x00, 0xAE, 0x53, 0x85, 0xED, 0x1F, 0xF0, 0x0E, 0x54, 0xF4, 0x4F, 0x69,
83 0xE1, 0x96, 0xFE, 0xCE, 0x15, 0xA9, 0x00, 0x7B, 0xF7, 0xDA, 0x86, 0xA5, 0xF8, 0xF0, 0x00, 0x8F,
84 0xF6, 0xE6, 0xE3, 0xD4, 0x39, 0xEE, 0x6D, 0xED, 0xB8, 0xE9, 0xC7, 0x1B, 0xC3, 0xBD, 0x01, 0x6D,
85 0x57, 0xD7, 0x85, 0xE0, 0x80, 0x7A, 0x1B, 0xE3, 0x45, 0x47, 0xCC, 0x17, 0x8C, 0xCC, 0x69, 0x9B,
86 0x7D, 0xB3, 0x94, 0xD5, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01
87 };
88 static const int rsa512_pub_len = 0x4A;
89
90 static const unsigned char rsa512_sec[]={
91 0x30, 0x82, 0x01, 0x3B, 0x02, 0x01, 0x00, 0x02, 0x41, 0x00, 0xAE, 0x53, 0x85, 0xED, 0x1F, 0xF0,
92 0x0E, 0x54, 0xF4, 0x4F, 0x69, 0xE1, 0x96, 0xFE, 0xCE, 0x15, 0xA9, 0x00, 0x7B, 0xF7, 0xDA, 0x86,
93 0xA5, 0xF8, 0xF0, 0x00, 0x8F, 0xF6, 0xE6, 0xE3, 0xD4, 0x39, 0xEE, 0x6D, 0xED, 0xB8, 0xE9, 0xC7,
94 0x1B, 0xC3, 0xBD, 0x01, 0x6D, 0x57, 0xD7, 0x85, 0xE0, 0x80, 0x7A, 0x1B, 0xE3, 0x45, 0x47, 0xCC,
95 0x17, 0x8C, 0xCC, 0x69, 0x9B, 0x7D, 0xB3, 0x94, 0xD5, 0x25, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
96 0x41, 0x00, 0x88, 0x07, 0xDD, 0x06, 0x00, 0x5A, 0x0E, 0x94, 0xF4, 0x5F, 0xD3, 0xBB, 0x99, 0x5C,
97 0x13, 0xEC, 0x8B, 0x08, 0x39, 0xB4, 0x5A, 0xED, 0x9F, 0x2D, 0xF5, 0xFA, 0x3A, 0x5C, 0xEC, 0x26,
98 0xF4, 0x3F, 0x46, 0xB6, 0x6C, 0x03, 0x0B, 0x85, 0x99, 0x95, 0x81, 0x2C, 0xEC, 0xE2, 0xA1, 0x92,
99 0xED, 0xBA, 0xAB, 0x16, 0xDC, 0xE0, 0xFD, 0xF7, 0xA6, 0x93, 0x4D, 0xA8, 0xEA, 0x67, 0xD4, 0x42,
100 0x1B, 0xB1, 0x02, 0x21, 0x00, 0xD6, 0x98, 0xF1, 0x7C, 0x33, 0xC9, 0x13, 0x2C, 0xB3, 0xC5, 0xB0,
101 0x37, 0x7B, 0xF9, 0x4A, 0xB4, 0x60, 0xFE, 0x0E, 0xB9, 0x5E, 0x96, 0xFC, 0x94, 0xD2, 0x6C, 0x7F,
102 0xE1, 0x14, 0xA6, 0xF7, 0xB3, 0x02, 0x21, 0x00, 0xCF, 0xF5, 0x91, 0xE2, 0x9B, 0x8E, 0xE0, 0xB5,
103 0x2D, 0x76, 0xB2, 0x93, 0x85, 0x30, 0xAE, 0x51, 0x69, 0x05, 0xC3, 0x20, 0x78, 0x88, 0x3D, 0x74,
104 0x4D, 0x10, 0xA1, 0x62, 0x84, 0xF8, 0x13, 0xC7, 0x02, 0x21, 0x00, 0xD0, 0x49, 0x9E, 0x89, 0xC8,
105 0xD1, 0xAF, 0x94, 0xC1, 0xE0, 0x6D, 0x0B, 0x4D, 0x7F, 0x47, 0xAD, 0x10, 0x3F, 0x47, 0x17, 0x50,
106 0xE2, 0x07, 0xC2, 0x83, 0x02, 0xE0, 0x94, 0x1C, 0xB1, 0x7A, 0xD5, 0x02, 0x20, 0x72, 0x95, 0xFE,
107 0x27, 0x5D, 0xCD, 0x71, 0x55, 0x83, 0x52, 0x86, 0xFD, 0x30, 0x03, 0x6D, 0xD9, 0x9F, 0xC3, 0xB4,
108 0x0B, 0x9D, 0x3E, 0x7C, 0x96, 0x2B, 0xAC, 0x81, 0x30, 0x36, 0xD2, 0x36, 0x9B, 0x02, 0x20, 0x67,
109 0xC7, 0xBC, 0x06, 0x91, 0x3C, 0xF7, 0xEF, 0x7F, 0x32, 0x58, 0xD0, 0xC0, 0xA8, 0x46, 0x72, 0x8F,
110 0xFB, 0x49, 0xC7, 0x29, 0x4E, 0xD6, 0x28, 0xB9, 0xF6, 0x26, 0x3D, 0xBD, 0xA1, 0xB7, 0xEA
111 };
112 static const int rsa512_sec_len = 0x13F;
113 #endif
114
115
116 /*---------------------------------------------------------------------------*
117 Function Definitions
118 *---------------------------------------------------------------------------*/
119
120 /*---------------------------------------------------------------------------*
121 Name: MyAlloc
122
123 Description: OS_Alloc wrapper function.
124 *---------------------------------------------------------------------------*/
MyAlloc(u32 size)125 static void* MyAlloc(u32 size)
126 {
127 void* ptr;
128 #ifdef PRINT_ALLOCATION
129 ptr = OS_Alloc(size+4);
130 *(u32*)ptr = size;
131 (u8*)ptr += 4;
132 total_allocated_size += size;
133 OS_TPrintf("Allocate %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
134 #else
135 ptr = OS_Alloc(size);
136 #endif
137 return ptr;
138 }
139
140 /*---------------------------------------------------------------------------*
141 Name: MyFree
142
143 Description: OS_Free wrapper function.
144 *---------------------------------------------------------------------------*/
MyFree(void * ptr)145 static void MyFree(void* ptr)
146 {
147 #ifdef PRINT_ALLOCATION
148 u32 size;
149 (u8*)ptr -= 4;
150 size = *(u32*)ptr;
151 total_allocated_size -= size;
152 OS_TPrintf("Free %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
153 #endif
154 OS_Free(ptr);
155 }
156
157 /*---------------------------------------------------------------------------*
158 Name: MyRealloc
159
160 Description: The realloc function.
161 *---------------------------------------------------------------------------*/
162 #ifndef MIN
163 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
164 #endif
165
MyRealloc(void * ptr,u32 new_size,u32 old_size)166 static void* MyRealloc(void* ptr, u32 new_size, u32 old_size)
167 {
168 void *buf;
169 #ifdef PRINT_ALLOCATION
170 u32 size;
171
172 buf = OS_Alloc(new_size+4);
173 *(u32*)buf = new_size;
174 (u8*)buf += 4;
175 total_allocated_size += new_size;
176 OS_TPrintf("Reallocate %d bytes from %p: total %d bytes\n", new_size, ptr, total_allocated_size);
177
178 (u8*)ptr -= 4;
179 size = *(u32*)ptr;
180 total_allocated_size -= size;
181 OS_TPrintf("Free(for realloc) %d bytes from %p: total %d bytes\n", size, ptr, total_allocated_size);
182 SDK_ASSERT(size == old_size);
183 OS_Free(ptr);
184 #else
185 if ((buf = OS_Alloc(new_size)) == NULL)
186 {
187 return NULL;
188 }
189
190 MI_CpuCopy8(ptr, buf, MIN(new_size, old_size));
191 OS_Free(ptr);
192 #endif
193
194 return buf;
195 }
196
197 /*---------------------------------------------------------------------------*
198 Name: NitroMain
199
200 Description: Initialization and main loop.
201
202 Arguments: None.
203
204 Returns: None.
205 *---------------------------------------------------------------------------*/
NitroMain(void)206 void NitroMain(void)
207 {
208 // Various types of initialization
209 OS_Init();
210 InitializeAllocateSystem();
211
212 DisplayInit();
213
214 if (RsaTest())
215 {
216 // Success
217 OS_TPrintf("------ Test Succeeded ------\n");
218 FillScreen(GX_RGB(0, 31, 0));
219 }
220 else
221 {
222 // Failed
223 OS_TPrintf("****** Test Failed ******\n");
224 FillScreen(GX_RGB(31, 0, 0));
225 }
226
227 // Main loop
228 while (TRUE)
229 {
230 // Waiting for the V-Blank
231 OS_WaitVBlankIntr();
232 }
233 }
234
235 /*---------------------------------------------------------------------------*
236 Name: VBlankIntr
237
238 Description: V-Blank interrupt vector.
239
240 Arguments: None.
241
242 Returns: None.
243 *---------------------------------------------------------------------------*/
VBlankIntr(void)244 static void VBlankIntr(void)
245 {
246 // Sets the IRQ check flag
247 OS_SetIrqCheckFlag(OS_IE_V_BLANK);
248 }
249
250 /*---------------------------------------------------------------------------*
251 Name: InitializeAllocateSystem
252
253 Description: Initializes the memory allocation system within the main memory arena.
254
255 Arguments: None.
256
257 Returns: None.
258 *---------------------------------------------------------------------------*/
InitializeAllocateSystem(void)259 static void InitializeAllocateSystem(void)
260 {
261 void *tempLo;
262 OSHeapHandle hh;
263
264 tempLo = OS_InitAlloc(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1);
265 OS_SetArenaLo(OS_ARENA_MAIN, tempLo);
266 hh = OS_CreateHeap(OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi());
267 if (hh < 0)
268 {
269 OS_Panic("ARM9: Fail to create heap...\n");
270 }
271 hh = OS_SetCurrentHeap(OS_ARENA_MAIN, hh);
272 }
273
274 /*---------------------------------------------------------------------------*
275 Name: DisplayInit
276
277 Description: Graphics initialization.
278
279 Arguments: None.
280
281 Returns: None.
282 *---------------------------------------------------------------------------*/
DisplayInit(void)283 static void DisplayInit(void)
284 {
285
286 GX_Init();
287 FX_Init();
288
289 GX_DispOff();
290 GXS_DispOff();
291
292 GX_SetDispSelect(GX_DISP_SELECT_SUB_MAIN);
293
294 OS_SetIrqFunction(OS_IE_V_BLANK, VBlankIntr);
295 (void)OS_EnableIrqMask(OS_IE_V_BLANK);
296 (void)GX_VBlankIntr(TRUE); // To generate V-Blank interrupt request
297 (void)OS_EnableIrq();
298
299
300 GX_SetBankForLCDC(GX_VRAM_LCDC_ALL);
301 MI_CpuClearFast((void *)HW_LCDC_VRAM, HW_LCDC_VRAM_SIZE);
302
303 MI_CpuFillFast((void *)HW_OAM, 192, HW_OAM_SIZE); // Clear OAM
304 MI_CpuClearFast((void *)HW_PLTT, HW_PLTT_SIZE); // Clear the standard palette
305
306 MI_CpuFillFast((void *)HW_DB_OAM, 192, HW_DB_OAM_SIZE); // Clear OAM
307 MI_CpuClearFast((void *)HW_DB_PLTT, HW_DB_PLTT_SIZE); // Clear the standard palette
308 MI_DmaFill32(3, (void *)HW_LCDC_VRAM_C, 0x7FFF7FFF, 256 * 192 * sizeof(u16));
309
310
311 GX_SetBankForOBJ(GX_VRAM_OBJ_256_AB); // Set VRAM-A,B for OBJ
312
313 GX_SetGraphicsMode(GX_DISPMODE_VRAM_C, // VRAM mode
314 (GXBGMode)0, // Dummy
315 (GXBG0As)0); // Dummy
316
317 GX_SetVisiblePlane(GX_PLANEMASK_OBJ); // Make OBJs visible
318 GX_SetOBJVRamModeBmp(GX_OBJVRAMMODE_BMP_1D_128K); // 2D mapping OBJ
319
320 OS_WaitVBlankIntr(); // Waiting for the end of the V-Blank interrupt
321 GX_DispOn();
322
323 }
324
325
326 /*---------------------------------------------------------------------------*
327 Name: FillScreen
328
329 Description: Fills the screen.
330
331 Arguments: col: FillColor
332
333 Returns: None.
334 *---------------------------------------------------------------------------*/
FillScreen(u16 col)335 static void FillScreen(u16 col)
336 {
337 MI_CpuFill16((void *)HW_LCDC_VRAM_C, col, 256 * 192 * 2);
338 }
339
340 /*---------------------------------------------------------------------------*
341 Name: RsaTest
342
343 Description: Test routine for the electronic signature functions.
344
345 Arguments: None.
346
347 Returns: TRUE if test succeeds.
348 *---------------------------------------------------------------------------*/
349 #define PrintResultEq( a, b, f ) \
350 { OS_TPrintf( ((a) == (b)) ? "[--OK--] " : "[**NG**] " ); (f) = (f) && ((a) == (b)); }
351
352 #define CheckAndPrintErr( result, str ) \
353 { if(OS_IsRunOnTwl() == TRUE){ \
354 if(result < 0) { OS_TPrintf( "Error: %d (%s)\n", result, str ); return FALSE;} \
355 }else{ \
356 if(result >= 0){ OS_TPrintf( "Error: %d (%s)\n", result, str ); return FALSE;} \
357 } \
358 }
359
RsaTest(void)360 static BOOL RsaTest(void)
361 {
362 BOOL flag = TRUE;
363
364 // Perform electronic signature operation test
365 {
366 char teststr[] = "Nintendo";
367 char encstr[128], decstr[128];
368 s32 result;
369 s32 len;
370 CRYPTORSAContext context;
371 CRYPTORSAEncryptInitParam encinitparam;
372 CRYPTORSAEncryptParam encparam;
373 CRYPTORSADecryptInitParam decinitparam;
374 CRYPTORSADecryptParam decparam;
375
376 CRYPTO_SetMemAllocator(MyAlloc, MyFree, MyRealloc);
377
378 /* RSA encode */
379 encinitparam.key = (void*)rsa512_pub;
380 encinitparam.key_len = rsa512_pub_len;
381 result = CRYPTO_RSA_EncryptInit(&context, &encinitparam);
382 CheckAndPrintErr(result, "CRYPTO_RSA_EncryptInit");
383
384 encparam.in = teststr;
385 encparam.in_len = strlen((char*)teststr);
386 encparam.out = encstr;
387 encparam.out_size = sizeof(encstr);
388 len = CRYPTO_RSA_Encrypt(&context, &encparam);
389 CheckAndPrintErr(len, "CRYPTO_RSA_Encrypt");
390
391 result = CRYPTO_RSA_EncryptTerminate(&context);
392 CheckAndPrintErr(result, "CRYPTO_RSA_EncryptTerminate");
393
394 /* RSA decode */
395 decinitparam.key = (void*)rsa512_sec;
396 decinitparam.key_len = rsa512_sec_len;
397 result = CRYPTO_RSA_DecryptInit(&context, &decinitparam);
398 CheckAndPrintErr(result, "CRYPTO_RSA_DecryptInit");
399
400 decparam.in = encstr;
401 decparam.in_len = (u32)len;
402 decparam.out = decstr;
403 decparam.out_size = sizeof(decstr);
404 result = CRYPTO_RSA_Decrypt(&context, &decparam);
405 CheckAndPrintErr(result, "CRYPTO_RSA_Decrypt");
406
407 result = CRYPTO_RSA_DecryptTerminate(&context);
408 CheckAndPrintErr(result, "CRYPTO_RSA_DecryptTerminate");
409
410 if(OS_IsRunOnTwl() == TRUE){
411 if( STD_CompareString(teststr, decstr) ){
412 OS_TPrintf( "Error: decrypted string is not match .\n" );
413 return FALSE;
414 }
415 }
416 }
417
418
419 return flag;
420 }
421
422
423 /*---------------------------------------------------------------------------*
424 Name: GetStringLength
425
426 Description: Gets the length of a string.
427
428 Arguments: str: Pointer to a string
429
430 Returns: Length of string.
431 *---------------------------------------------------------------------------*/
GetStringLength(char * str)432 static u32 GetStringLength(char* str)
433 {
434 u32 i;
435 for (i = 0; ; i++)
436 {
437 if (*(str++) == '\0')
438 {
439 return i;
440 }
441 }
442 }
443
444 /*---------------------------------------------------------------------------*
445 Name: PrintBinary
446
447 Description: Binary array output.
448
449 Arguments: ptr: Memory location to output
450 len: Length to output
451
452 Returns: None.
453 *---------------------------------------------------------------------------*/
PrintBinary(u8 * ptr,int len)454 static void PrintBinary(u8* ptr, int len)
455 {
456 #ifndef SDK_FINALROM
457 int i;
458 for (i = 0; i < len; i++)
459 {
460 if (i != 0)
461 {
462 OS_PutString(":");
463 }
464 OS_TPrintf("%02x", ptr[i]);
465 }
466 #else
467 #pragma unused(ptr,len)
468 #endif
469 return;
470 }
471
472 /*---------------------------------------------------------------------------*
473 End of file
474 *---------------------------------------------------------------------------*/
475