sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
udnl.c
1#include <dmacman.h>
2#include <ioman.h>
3#include <intrman.h>
4#include <loadcore.h>
5#include <stdio.h>
6#include <sysmem.h>
7#include <sysclib.h>
8#include <thbase.h>
9#include <mipscopaccess.h>
10
11#include "ELF.h"
12#include "COFF.h"
13
14#define MODNAME "UpDate DownLoader"
15
16IRX_ID(MODNAME, 1, 1);
17
18#ifdef UDNL_T300
19int CpuExecuteKmode(void *function, ...); // Exactly the same function as INTRMAN's export 14.
20#endif
21
22//#define DEBUG 1 //Comment out to disable debug messages.
23#ifdef DEBUG
24#define DEBUG_PRINTF(args...) printf(args)
25#else
26#define DEBUG_PRINTF(args...)
27#endif
28
29#define FULL_UDNL 1 // Comment out to build a UDNL module that updates the IOP with only its payload.
30#define MAX_MODULES 256
31
32#define alloca(size) __builtin_alloca(size) // The homebrew PS2SDK lacks alloca.h.
33
34// Function prototypes
35static void CopySection(const void *module, void *buffer, unsigned int FileSize);
36static void *AllocMemory(int nbytes);
37
38#ifdef FULL_UDNL
39/* Evil function. */
40/* 0x00000000 */
41/*
42int isIllegalBootDevice(const char *arg1)
43{
44#ifdef UDNL_T300
45 unsigned int temp1, temp2, temp3, DeviceHash;
46
47 while (*path == ' ')
48 path++;
49
50 temp1 = *path++;
51 temp2 = *path++;
52 temp3 = *path++;
53
54 DeviceHash = (((((temp1 << 8) | temp2) << 8) | temp3) << 8) ^ 0x72e7c42f;
55
56 // "rom", "host" and "cdrom".
57 if ((DeviceHash >> 8 == 0x000088A9) || (DeviceHash == 0x1A88B75B) || ((DeviceHash == 0x1183b640)) && (*path++) == 'm'))
58 {
59 return ((*path - 0x30) < 0x0b ? 1 : 0);
60 }
61 else {
62 return 1;
63 }
64#else
65 // Eliminate spaces from the path.
66 if (arg1[0] == ' ') {
67 arg1++;
68 do {
69 arg1++;
70 } while (arg1[0] == ' ');
71
72 arg1--;
73 }
74
75 if (((arg1[0] | 0x20) == 'm') && ((arg1[1] | 0x20) == 'c')) { //"mc"
76 arg1 += 2;
77 goto end_func1;
78 } else if (((arg1[0] | 0x20) == 'h') && ((arg1[1] | 0x20) == 'd')) { //"hd"
79 arg1 += 2;
80 goto end_func1;
81 } else if (((arg1[0] | 0x20) == 'n') && ((arg1[1] | 0x20) == 'e') && ((arg1[2] | 0x20) == 't')) { //"net"
82 arg1 += 3;
83 goto end_func1;
84 } else if (((arg1[0] | 0x20) == 'd') && ((arg1[1] | 0x20) == 'e') && ((arg1[2] | 0x20) == 'v')) { //"dev"
85 arg1 += 3;
86 goto end_func1;
87 } else
88 return 0;
89
90end_func1:
91 return ((*arg1 - 0x30 < 0x0b) ? 1 : 0); // '0' to '9' and ':'
92#endif
93}
94*/
95#endif
96
97/*
98 0x00 - RAM size in MB.
99 0x04 - The boot mode (0 = hard reset, 1 = soft reset, 2 = update reset, 3 = update complete).
100 0x08 - Updater command line (Only for when boot mode = 2).
101 0x0C - Pointer to the entry point of the first module.
102 0x10 - Result from QueryMemSize() - 0x00200000
103 0x1C - pointer to the buffer (Size: Size of images + MAX_MODULES*sizeof(void*) + sizeof(struct ResetData) bytes)
104*/
105
106struct ResetData
107{
108 unsigned int MemSize; /* 0x00 */
109 unsigned int BootMode; /* 0x04 */
110 const char *command; /* 0x08 */
111 void *StartAddress; /* 0x0C */
112 void *IOPRPBuffer; /* 0x10 */
113 unsigned int IOPRPBufferSize; /* 0x14 */
114 unsigned int NumModules; /* 0x18 */
115 const void **ModData; /* 0x1C */
116};
117
118#ifdef FULL_UDNL
119#ifdef UDNL_T300
120static int var_00001e20 = 0; /* 0x00001e20 - Not sure what this is, but it's probably a verbosity level flag, although unused. */
121#else
122static int var_00001850 = 0; /* 0x00001850 - Not sure what this is, but it's probably a verbosity level flag, although unused. */
123#endif
124#endif
125
126#ifdef USE_EMBEDDED_IOPRP
127extern unsigned char IOPRP_img[];
128extern unsigned int size_IOPRP_img;
129#endif
130
132{ /* 12 bytes */
133 const void *ImageStart;
134 const void *RomdirStart;
135 const void *RomdirEnd;
136};
137
139{ /* 24 bytes */
140 const char *filename;
141 int fd;
142 int size;
143 struct RomImgData stat;
144};
145
146struct RomDirEntry
147{
148 char name[10];
149 unsigned short int ExtInfoEntrySize;
150 unsigned int size;
151};
152
153/* 0x00001220 */
154static void *GetIOPRPStat(const void *start, const void *end, struct RomImgData *ImageStat)
155{
156 const unsigned int *ptr, *ptr2;
157 unsigned int offset;
158
159 ptr = start;
160 offset = 0;
161 while ((unsigned int)ptr < (unsigned int)end) {
162 ptr2 = &ptr[7];
163 // Scan for RESET\0\0\0\0\0. The record should have a filesize of equal to its offset from the start of the image.
164 if (ptr[0] == 0x45534552 && ptr2[-6] == 0x54 && (*(unsigned short int *)&ptr2[-5] == 0) && (((ptr2[-4] + 0xF) & 0xFFFFFFF0) == offset)) {
165 ImageStat->ImageStart = start;
166 ImageStat->RomdirStart = ptr;
167 ImageStat->RomdirEnd = (void *)((unsigned int)ptr + *ptr2);
168 return ImageStat;
169 }
170
171 offset += sizeof(struct RomDirEntry);
172 ptr += 4;
173 }
174
175 ImageStat->ImageStart = 0;
176 return NULL;
177}
178
180{
181 const struct RomDirEntry *romdirent;
182 const void *data;
183 const void *extinfo;
184 unsigned int padding;
185};
186
187/* 0x000012c8 */
188static struct RomdirFileStat *GetFileStatFromImage(const struct RomImgData *ImageStat, const char *filename, struct RomdirFileStat *stat)
189{
190 unsigned int i, offset, ExtInfoOffset;
191 unsigned char filename_temp[12];
192 const struct RomDirEntry *RomdirEntry;
193#ifdef UDNL_T300
194 struct RomdirFileStat *result;
195#endif
196
197 offset = 0;
198 ExtInfoOffset = 0;
199 ((unsigned int *)filename_temp)[0] = 0;
200 ((unsigned int *)filename_temp)[1] = 0;
201 ((unsigned int *)filename_temp)[2] = 0;
202 for (i = 0; *filename >= 0x21 && i < sizeof(filename_temp); i++) {
203 filename_temp[i] = *filename;
204 filename++;
205 }
206
207 if (ImageStat->RomdirStart != NULL) {
208 RomdirEntry = ImageStat->RomdirStart;
209
210 do {
211 if (((unsigned int *)filename_temp)[0] == ((unsigned int *)RomdirEntry->name)[0] && ((unsigned int *)filename_temp)[1] == ((unsigned int *)RomdirEntry->name)[1] && (*(unsigned short int *)&((unsigned int *)filename_temp)[2] == *(unsigned short int *)&((unsigned int *)RomdirEntry->name)[2])) {
212
213 stat->romdirent = RomdirEntry;
214 stat->data = (void *)((u8 *)(ImageStat->ImageStart) + offset);
215 stat->extinfo = NULL;
216
217 if (RomdirEntry->ExtInfoEntrySize > 0) {
218 stat->extinfo = (void *)((unsigned int)ImageStat->RomdirEnd + ExtInfoOffset);
219#ifdef UDNL_T300
220 result = stat;
221 goto end;
222#endif
223 }
224
225#ifndef UDNL_T300
226 return stat;
227#endif
228 }
229
230 offset += (RomdirEntry->size + 0xF) & 0xFFFFFFF0;
231 ExtInfoOffset += RomdirEntry->ExtInfoEntrySize;
232 RomdirEntry++;
233 } while (((unsigned int *)RomdirEntry->name)[0] != 0x00000000);
234
235#ifdef UDNL_T300
236 result = NULL;
237#endif
238 }
239#ifdef UDNL_T300
240 else {
241 result = NULL;
242 }
243#endif
244
245#ifdef UDNL_T300
246end:
247 return result;
248#else
249 return NULL;
250#endif
251}
252
253/* 0x0000055c */
254static void ScanImagesForFile(const struct ImageData *ImageDataBuffer, unsigned int NumFiles, struct RomdirFileStat *stat, const char *filename)
255{
256 const struct ImageData *ImageData;
257
258 if (NumFiles > 0) {
259 int i;
260
261 /*
262 Let f(x)=((x-1)*2+(x-1))*8;
263 f(1)=((1-1)*2+(1-1))*8=0
264 f(2)=((2-1)*2+(2-1))*8=24
265 f(3)=((3-1)*2+(3-1))*8=48
266
267 ImageDataBuffer+(NumFiles<<1+NumFiles)<<3
268 */
269
270 i = NumFiles - 1;
271 ImageData = &ImageDataBuffer[i];
272
273 do {
274 if (ImageData->filename != NULL) {
275 if (GetFileStatFromImage(&ImageData->stat, filename, stat) != 0) {
276 DEBUG_PRINTF("File: %s, image: %s\n", filename, ImageData->filename);
277 return;
278 }
279 }
280
281 i--;
282 ImageData--;
283 } while (i >= 0);
284 }
285
286#ifdef UDNL_T300
287 printf("kupdate: panic ! \'%s\' not found\n", filename);
288#else
289 printf("panic ! \'%s\' not found\n", filename);
290#endif
291 __builtin_trap();
292}
293
294#ifdef UDNL_T300
295static void TerminateResidentLibraries(const char *message, unsigned int options, int mode)
296{
297 lc_internals_t *LoadcoreData;
298 iop_library_t *ModuleData, *NextModule;
299 void **ExportTable;
300
301 (void)message;
302 (void)options;
303
304 if ((LoadcoreData = GetLoadcoreInternalData()) != NULL) {
305 ModuleData = LoadcoreData->let_next;
306 while (ModuleData != NULL) {
307 NextModule = ModuleData->prev;
308
309 if (mode == 2) {
310 if (!(ModuleData->flags & 6)) {
311 ModuleData = NextModule;
312 continue;
313 }
314 } else if ((ModuleData->flags & 6) == 2) { // Won't ever happen?
315 ModuleData = NextModule;
316 continue;
317 }
318
319 ExportTable = ModuleData->exports;
320 if (ExportTable[1] != NULL && ExportTable[2] != NULL) {
321 int (*pexit)(int arg1);
322
323 pexit = ExportTable[2];
324 pexit(0);
325 }
326
327 ModuleData = NextModule;
328 }
329 }
330}
331
332struct ssbus_regs
333{
334 volatile unsigned int *address, *delay;
335};
336
337static struct ssbus_regs ssbus_regs[] = { // 0x00001e24
338 {
339 (volatile unsigned int *)0xbf801000,
340 (volatile unsigned int *)0xbf801008},
341 {(volatile unsigned int *)0xbf801400,
342 (volatile unsigned int *)0xbf80100C},
343 {(volatile unsigned int *)0xbf801404,
344 (volatile unsigned int *)0xbf801014},
345 {(volatile unsigned int *)0xbf801408,
346 (volatile unsigned int *)0xbf801018},
347 {(volatile unsigned int *)0xbf80140C,
348 (volatile unsigned int *)0xbf801414},
349 {(volatile unsigned int *)0xbf801410,
350 (volatile unsigned int *)0xbf80141C},
351 {NULL,
352 NULL}};
353
354// 0x00000f80
355static volatile unsigned int *func_00000f80(volatile unsigned int *address)
356{
357 struct ssbus_regs *pSSBUS_regs;
358
359 pSSBUS_regs = ssbus_regs;
360 while (pSSBUS_regs->address != NULL) {
361 if (pSSBUS_regs->address == address)
362 break;
363 pSSBUS_regs++;
364 }
365
366 return pSSBUS_regs->delay;
367}
368
369// 0x00001b38
370void func_00001b38(unsigned int arg1);
371
372// 0x00000c98
373static void TerminateResidentEntriesDI(unsigned int options)
374{
375 int prid;
376 volatile unsigned int **pReg;
377
378 TerminateResidentLibraries(" kupdate:di: Terminate resident Libraries\n", options, 0);
379
380 prid = get_mips_cop_reg(0, COP0_REG_PRId);
381
382 if (!(options & 1)) {
383 pReg = (prid < 0x10 || ((*(volatile unsigned int *)0xbf801450) & 8)) ? *(volatile unsigned int ***)0xbfc02008 : *(volatile unsigned int ***)0xbfc0200C;
384
385 while (pReg[0] != 0) {
386 if (func_00000f80(pReg[0]) != 0)
387 pReg[0] = (void *)0xFF;
388 pReg[0] = pReg[1];
389 pReg += 2;
390 }
391 }
392 if (!(options & 2)) {
393 func_00001b38((prid < 0x10 || ((*(volatile unsigned int *)0xbf801450) & 8)) ? *(volatile unsigned int *)0xbfc02010 : *(volatile unsigned int *)0xbfc02014);
394 }
395}
396#endif
397
399{
400 unsigned int ModuleType; // 0x00
401 void *EntryPoint; // 0x04
402 void *gp; // 0x08
403 void *text_start; // 0x0C
404 unsigned int text_size; // 0x10
405 unsigned int data_size; // 0x14
406 unsigned int bss_size; // 0x18
407 unsigned int MemSize; // 0x1C
408 struct iopmod_id *mod_id; // 0x20
409 unsigned int unknown_24; // 0x24
410};
411
412#ifdef UDNL_T300
413void func_00001930(void);
414#else
415void func_00001440(void);
416#endif
417
418enum IOP_MODULE_TYPES {
419 IOP_MOD_TYPE_COFF = 1,
420 IOP_MOD_TYPE_2,
421 IOP_MOD_TYPE_ELF,
422 IOP_MOD_TYPE_IRX
423};
424
425/* 0x00000b70 */
426static int InitModuleInfo(const void *module, struct ModuleInfo *ModuleInfo)
427{
428 unsigned int Ident_10;
429 const struct scnhdr *COFF_ScnHdr;
430 const AOUTHDR *COFF_AoutHdr;
431 const elf_header_t *ELF_Hdr;
432 const elf_pheader_t *ELF_phdr;
433 const struct iopmod *iopmod;
434
435 /*
436 sizeof(struct coff_filehdr) = 20 bytes
437 sizeof(AOUTHDR) = 56 bytes
438 sizeof(struct scnhdr) = 40 bytes
439 */
440
441 memcpy(&Ident_10, &((struct coff_filehdr *)module)->f_opthdr, 4);
442 COFF_AoutHdr = (AOUTHDR *)((unsigned int)module + sizeof(struct coff_filehdr));
443 COFF_ScnHdr = (struct scnhdr *)((unsigned int)module + sizeof(struct coff_filehdr) + sizeof(AOUTHDR));
444 if (((struct coff_filehdr *)module)->f_magic == MIPSELMAGIC && COFF_AoutHdr->magic == OMAGIC && ((struct coff_filehdr *)module)->f_nscns < 0x20 && ((Ident_10 & 0x0002FFFF) == 0x20038) && COFF_ScnHdr->s_paddr == COFF_AoutHdr->text_start) {
445 if (COFF_AoutHdr->vstamp != 0x7001) {
446 /* 0x00000bf8 - COFF */
447 ModuleInfo->ModuleType = IOP_MOD_TYPE_COFF;
448 ModuleInfo->EntryPoint = (void *)COFF_AoutHdr->entry;
449 ModuleInfo->gp = (void *)COFF_AoutHdr->gp_value;
450 ModuleInfo->text_start = (void *)COFF_AoutHdr->text_start;
451 ModuleInfo->text_size = COFF_AoutHdr->tsize;
452 ModuleInfo->data_size = COFF_AoutHdr->dsize;
453 ModuleInfo->bss_size = COFF_AoutHdr->bsize;
454 ModuleInfo->MemSize = COFF_AoutHdr->bss_start + COFF_AoutHdr->bsize - COFF_AoutHdr->text_start;
455 ModuleInfo->mod_id = COFF_AoutHdr->mod_id;
456
457 return ModuleInfo->ModuleType;
458 } else {
459 return -1;
460 }
461 } else {
462 /* 0x00000C68 - ELF */
463 ELF_Hdr = module;
464 ELF_phdr = (elf_pheader_t *)((unsigned int)module + ELF_Hdr->phoff);
465
466 if (((unsigned short int *)ELF_Hdr->ident)[2] == 0x101 && ELF_Hdr->machine == 8 && ELF_Hdr->phentsize == sizeof(elf_pheader_t) && ELF_Hdr->phnum == 2 && (ELF_phdr->type == (SHT_LOPROC | SHT_LOPROC_IOPMOD)) && (ELF_Hdr->type == ELF_TYPE_SCE_IRX || ELF_Hdr->type == 2)) {
467 ModuleInfo->ModuleType = ELF_Hdr->type == 0xFF80 ? IOP_MOD_TYPE_IRX : IOP_MOD_TYPE_ELF;
468
469 /* 0x00000ce8 */
470 iopmod = (struct iopmod *)((unsigned int)module + ELF_phdr->offset);
471 ModuleInfo->EntryPoint = (void *)iopmod->EntryPoint;
472 ModuleInfo->gp = (void *)iopmod->gp;
473 ModuleInfo->text_start = (void *)ELF_phdr[1].vaddr;
474 ModuleInfo->text_size = iopmod->text_size;
475 ModuleInfo->data_size = iopmod->data_size;
476 ModuleInfo->bss_size = iopmod->bss_size;
477 ModuleInfo->MemSize = ELF_phdr[1].memsz;
478 ModuleInfo->mod_id = iopmod->mod_id;
479
480 return ModuleInfo->ModuleType;
481 } else {
482 return -1;
483 }
484 }
485}
486
487/* 0x000011c8 */
488static void CopySection(const void *module, void *buffer, unsigned int FileSize)
489{
490 unsigned int *dst;
491 const unsigned int *src;
492 const void *src_end;
493
494 dst = buffer;
495 src = module;
496 src_end = (const void *)((unsigned int)module + (FileSize >> 2 << 2));
497 while ((unsigned int)src < (unsigned int)src_end) {
498 *dst = *src;
499 src++;
500 dst++;
501 }
502}
503
504/* 0x00001200 */
505static void ZeroSection(unsigned int *buffer, unsigned int NumWords)
506{
507 while (NumWords > 0) {
508 *buffer = 0;
509 NumWords--;
510 buffer++;
511 }
512}
513
514/* 0x00000f08 */
515static void LoadELFModule(const void *module)
516{
517 const elf_header_t *ELF_Hdr;
518 const elf_pheader_t *ELF_phdr;
519
520 ELF_Hdr = module;
521 ELF_phdr = (elf_pheader_t *)((unsigned int)module + ELF_Hdr->phoff);
522
523 CopySection((void *)((unsigned int)module + ELF_phdr[1].offset), (void *)ELF_phdr[1].vaddr, ELF_phdr[1].filesz);
524
525 if (ELF_phdr[1].filesz < ELF_phdr[1].memsz) {
526 ZeroSection((unsigned int *)(ELF_phdr[1].vaddr + ELF_phdr[1].filesz), (ELF_phdr[1].memsz - ELF_phdr[1].filesz) >> 2);
527 }
528}
529
530/* 0x00000e88 */
531static void LoadCOFFModule(const void *module)
532{
533 const AOUTHDR *COFF_AoutHdr;
534 const struct scnhdr *ScnHdr;
535
536 /*
537 sizeof(struct coff_filehdr) = 20 bytes
538 sizeof(AOUTHDR) = 56 bytes
539 sizeof(struct scnhdr) = 40 bytes
540 */
541
542 COFF_AoutHdr = (AOUTHDR *)((unsigned int)module + sizeof(struct coff_filehdr));
543 ScnHdr = (struct scnhdr *)((unsigned int)module + sizeof(struct coff_filehdr) + sizeof(AOUTHDR));
544
545 CopySection((void *)((unsigned int)module + ScnHdr[0].s_size), (void *)COFF_AoutHdr->text_start, COFF_AoutHdr->tsize);
546 CopySection((void *)((unsigned int)module + COFF_AoutHdr->tsize), (void *)COFF_AoutHdr->data_start, COFF_AoutHdr->dsize);
547
548 if (COFF_AoutHdr->bss_start != 0 && COFF_AoutHdr->bsize != 0) {
549 ZeroSection((unsigned int *)COFF_AoutHdr->bss_start, COFF_AoutHdr->bsize >> 2);
550 }
551}
552
553/* 0x00000f6c */
554static void LoadIRXModule(const void *module, struct ModuleInfo *ModuleInfo)
555{
556 const elf_header_t *ELF_hdr;
557 const elf_pheader_t *ELF_phdr;
558 const elf_shdr_t *ELF_shdr, *CurrentELF_shdr;
559 unsigned int NumRelocs, i, SectionNum;
560 const elf_rel *ELF_relocation;
561 unsigned int temp, *WordPatchLocation;
562
563 ELF_hdr = (elf_header_t *)module;
564 ELF_phdr = (elf_pheader_t *)((unsigned int)module + ELF_hdr->phoff);
565
566 ModuleInfo->gp = (void *)((u8 *)ModuleInfo->gp + (unsigned int)ModuleInfo->text_start);
567 ModuleInfo->EntryPoint = (void *)((u8 *)ModuleInfo->EntryPoint + (unsigned int)ModuleInfo->text_start);
568
569 if (ModuleInfo->mod_id != (void *)0xFFFFFFFF) {
570 ModuleInfo->mod_id = (struct iopmod_id *)((u8 *)ModuleInfo->mod_id + (unsigned int)ModuleInfo->text_start);
571 }
572
573 ELF_shdr = (elf_shdr_t *)((unsigned int)module + ELF_hdr->shoff);
574
575 CopySection((void *)((unsigned int)module + ELF_phdr[1].offset), ModuleInfo->text_start, ELF_phdr[1].filesz);
576
577 /* 0x00000fec */
578 if (ELF_phdr[1].filesz < ELF_phdr[1].memsz) {
579 ZeroSection((unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_phdr[1].filesz), (ELF_phdr[1].memsz - ELF_phdr[1].filesz) >> 2);
580 }
581
582 /* 0x00001048 */
583 for (SectionNum = 0, CurrentELF_shdr = ELF_shdr + 1; SectionNum < ELF_hdr->shnum; SectionNum++, CurrentELF_shdr++) {
584 if (CurrentELF_shdr->type == SHT_REL) {
585 NumRelocs = CurrentELF_shdr->size / CurrentELF_shdr->entsize;
586
587 /* 0x0000107c - Warning: beware of sign extension! The code here depends on sign extension. */
588 for (i = 0, ELF_relocation = (elf_rel *)((unsigned int)module + CurrentELF_shdr->offset); i < NumRelocs; i++, ELF_relocation++) {
589 // DEBUG_PRINTF("Reloc %d: %p\n", (unsigned char)ELF_relocation->info&0xFF, (u8 *)(ModuleInfo->text_start)+ELF_relocation->offset); //Code for debugging only: Not originally present.
590
591 switch (ELF_relocation->info & 0xFF) {
592 case R_MIPS_NONE:
593 break;
594 case R_MIPS_16:
595 WordPatchLocation = (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset);
596 *WordPatchLocation = (*WordPatchLocation & 0xFFFF0000) | (((unsigned int)ModuleInfo->text_start + *(short int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset)) & 0xFFFF);
597 break;
598 case R_MIPS_32:
599 WordPatchLocation = (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset);
600 *WordPatchLocation += (unsigned int)ModuleInfo->text_start;
601 break;
602 case R_MIPS_REL32:
603 break;
604 case R_MIPS_26:
605 WordPatchLocation = (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset);
606 *WordPatchLocation = (((unsigned int)ModuleInfo->text_start + ((*WordPatchLocation & 0x03FFFFFF) << 2 | ((unsigned int)WordPatchLocation & 0xF0000000))) << 4 >> 6) | (*WordPatchLocation & 0xFC000000);
607 break;
608 case R_MIPS_HI16: // 0x00001120 - Ouch. D:
609 temp = (((unsigned int)*(unsigned short int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset)) << 16) + *(short int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation[1].offset);
610 temp += (unsigned int)ModuleInfo->text_start;
611 WordPatchLocation = (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation->offset);
612 *WordPatchLocation = (((temp >> 15) + 1) >> 1 & 0xFFFF) | (*WordPatchLocation & 0xFFFF0000);
613 WordPatchLocation = (unsigned int *)((u8 *)(ModuleInfo->text_start) + ELF_relocation[1].offset);
614 *WordPatchLocation = (*WordPatchLocation & 0xFFFF0000) | (temp & 0xFFFF);
615 ELF_relocation++;
616 i++;
617 break;
618 case R_MIPS_LO16:
619 break;
620 }
621 }
622 }
623 }
624}
625
627{
628 struct ModInfo *next; // 0x00
629 const char *name; // 0x04
630 unsigned short int version; // 0x08
631 unsigned short int newflags; // 0x0A
632 unsigned short int id; // 0x0C
633 unsigned short int flags; // 0x0E
634 void *EntryPoint; // 0x10
635 void *gp; // 0x14
636 void *text_start; // 0x18
637 unsigned int text_size; // 0x1C
638 unsigned int data_size; // 0x20
639 unsigned int bss_size; // 0x24
640 unsigned int unused1; // 0x28
641 unsigned int unused2; // 0x2C
642};
643
644/* 0x00000df8 - Initializes the module information structure, which exists 0x30 bytes before the module itself. */
645static void InitLoadedModInfo(struct ModuleInfo *ModuleInfo, struct ModInfo *ModInfo)
646{
647 ModInfo->next = NULL;
648 ModInfo->name = NULL;
649 ModInfo->version = 0;
650 ModInfo->newflags = 0;
651 ModInfo->id = 0;
652
653 if (ModuleInfo->mod_id != (void *)0xFFFFFFFF) {
654 ModInfo->name = ModuleInfo->mod_id->name;
655 ModInfo->version = ModuleInfo->mod_id->version;
656 }
657
658 ModInfo->EntryPoint = ModuleInfo->EntryPoint;
659 ModInfo->gp = ModuleInfo->gp;
660 ModInfo->text_start = ModuleInfo->text_start;
661 ModInfo->text_size = ModuleInfo->text_size;
662 ModInfo->data_size = ModuleInfo->data_size;
663 ModInfo->bss_size = ModuleInfo->bss_size;
664}
665
666/* 0x00000d60 */
667static int LoadModule(const void *module, struct ModuleInfo *ModuleInfo)
668{
669 switch (ModuleInfo->ModuleType) {
670 case IOP_MOD_TYPE_ELF:
671 LoadELFModule(module);
672 break;
673 case IOP_MOD_TYPE_COFF:
674 LoadCOFFModule(module);
675 break;
676 case IOP_MOD_TYPE_IRX:
677 LoadIRXModule(module, ModuleInfo);
678 break;
679 default:
680 return -1;
681 }
682
683 /* 0x00000dd4 */
684 InitLoadedModInfo(ModuleInfo, (void *)((u8 *)(ModuleInfo->text_start) - 0x30));
685
686 return 0;
687}
688
689/* 0x000009d0 */
690#ifdef UDNL_T300
691static void BeginBootupSequence(struct ResetData *ResetData, unsigned int options)
692#else
693static void BeginBootupSequence(struct ResetData *ResetData)
694#endif
695{
696 struct ModuleInfo LoadedModules[2];
697 int MemSizeInBytes;
698 int (*ModuleEntryPoint)(int arg1);
699 void *FreeMemStart;
700
701#ifdef UDNL_T300
702 TerminateResidentEntriesDI(options);
703
704 dmac_set_dpcr(0);
705 dmac_set_dpcr2(0);
706 dmac_set_dpcr3(0);
707#endif
708
709 MemSizeInBytes = ResetData->MemSize << 20;
710
711 // Load SYSMEM
712 switch (InitModuleInfo(ResetData->ModData[0], &LoadedModules[0])) {
713 case IOP_MOD_TYPE_2:
714 case IOP_MOD_TYPE_IRX:
715 LoadedModules[0].text_start = (void *)((unsigned int)ResetData->StartAddress + 0x30);
716 // Fall through.
717 case IOP_MOD_TYPE_COFF:
718 case IOP_MOD_TYPE_ELF:
719 LoadModule(ResetData->ModData[0], &LoadedModules[0]);
720 break;
721 }
722
723 /* 0x00000a58 */
724#ifdef UDNL_T300
725 func_00001930();
726#else
727 func_00001440();
728#endif
729
730 ModuleEntryPoint = LoadedModules[0].EntryPoint;
731 FreeMemStart = (void *)ModuleEntryPoint(MemSizeInBytes);
732
733 // Load LOADCORE
734 switch (InitModuleInfo(ResetData->ModData[1], &LoadedModules[1])) {
735 case IOP_MOD_TYPE_2:
736 case IOP_MOD_TYPE_IRX:
737 LoadedModules[1].text_start = (void *)((unsigned int)FreeMemStart + 0x30);
738 // Fall through.
739 case IOP_MOD_TYPE_COFF:
740 case IOP_MOD_TYPE_ELF:
741 LoadModule(ResetData->ModData[1], &LoadedModules[1]);
742 break;
743 }
744
745 /* 0x00000ad0 */
746#ifdef UDNL_T300
747 func_00001930();
748#else
749 func_00001440();
750#endif
751
752 ResetData->StartAddress = LoadedModules[0].text_start;
753
754 ModuleEntryPoint = LoadedModules[1].EntryPoint;
755 ModuleEntryPoint((int)ResetData); // LOADCORE will start the bootup sequence.
756
757 // HALT loop
758 while (1)
759 *(volatile unsigned char *)0x80000000 = 2;
760}
761
762/* 0x00000b08 */
763static void *ParseStartAddress(const char **line)
764{
765 const char *ptr;
766 void *address;
767
768 ptr = *line;
769 address = 0;
770 while (*ptr >= 0x30) {
771 unsigned char character;
772
773 character = *ptr;
774 ptr++;
775 if (character < ':') {
776 character -= 0x30;
777 } else if (character < 'a') {
778 character -= 0x4B;
779 } else {
780 character -= 0x6B;
781 }
782
783 address = (void *)(((unsigned int)address << 4) + character);
784 }
785
786 *line = ptr;
787
788 return address;
789}
790
792{
793 unsigned short int data;
794 unsigned short int header; // Upper 8 bits contain the type.
795};
796
797/* 0x000013d8 */
798static const struct ExtInfoField *GetFileInfo(const struct RomdirFileStat *stat, int mode)
799{
800 const struct RomDirEntry *RomDirEnt;
801 const void *extinfo_end;
802 const struct ExtInfoField *ExtInfoField;
803
804 RomDirEnt = stat->romdirent;
805 extinfo_end = (unsigned char *)stat->extinfo + (RomDirEnt->ExtInfoEntrySize >> 2 << 2);
806 ExtInfoField = stat->extinfo;
807
808 while ((unsigned int)ExtInfoField < (unsigned int)extinfo_end) {
809 unsigned int ExtInfoHeader;
810
811 ExtInfoHeader = *(unsigned int *)ExtInfoField;
812
813 if (ExtInfoHeader >> 24 == (unsigned int)mode) {
814 return ExtInfoField;
815 }
816
817 ExtInfoField = (const struct ExtInfoField *)((const u8 *)ExtInfoField + ((ExtInfoHeader >> 16 & 0xFC) + 4));
818 }
819
820 return NULL;
821}
822
823/* 0x00000878 - Scans through all loaded IOPRP images for the newest version of the specified module. */
824static struct RomdirFileStat *SelectModuleFromImages(const struct ImageData *ImageDataBuffer, unsigned int NumFiles, const char *line, struct RomdirFileStat *stat_out)
825{
826 char filename[32];
827 int count, NumFilesRemaining, ImageFileIndexNumber;
828 struct RomdirFileStat *result;
829 const struct ImageData *ImageDataPtr;
830 struct RomdirFileStat stat;
831 const struct ExtInfoField *ExtInfofield;
832 unsigned int HighestFileVersionNum;
833
834 count = 0;
835 if (*line >= 0x21) {
836 do {
837 filename[count] = *line;
838 count++;
839 line++;
840 } while (count < 10 && *line >= 0x21);
841 }
842 filename[count] = '\0';
843
844 /* 0x000008e0 */
845 ImageFileIndexNumber = -1;
846 HighestFileVersionNum = 0;
847 NumFilesRemaining = NumFiles - 1;
848 {
849 ImageDataPtr = &ImageDataBuffer[NumFilesRemaining];
850
851 do {
852 if (ImageDataPtr->filename != NULL) {
853 if (GetFileStatFromImage(&ImageDataPtr->stat, filename, &stat) != NULL) {
854 unsigned short int FileVersionNum;
855
856 ExtInfofield = GetFileInfo(&stat, 2);
857 FileVersionNum = 0;
858 GetFileInfo(&stat, 3);
859
860 /* 0x00000940 */
861 if (ExtInfofield != NULL) {
862 FileVersionNum = ExtInfofield->data;
863 }
864
865 if (ImageFileIndexNumber < 0 || HighestFileVersionNum < FileVersionNum) {
866 ImageFileIndexNumber = NumFilesRemaining;
867 HighestFileVersionNum = FileVersionNum;
868
869 DEBUG_PRINTF("SelectModule: %s, %s, 0x%x\n", filename, ImageDataPtr->filename, FileVersionNum);
870 }
871 }
872 }
873 ImageDataPtr--;
874 } while (--NumFilesRemaining >= 0);
875 }
876
877 if (ImageFileIndexNumber >= 0) {
878 result = GetFileStatFromImage(&ImageDataBuffer[ImageFileIndexNumber].stat, filename, stat_out);
879 } else
880 result = NULL;
881
882 return result;
883}
884
885// Code for debugging only - not originally present.
886#ifdef DEBUG
887static void DisplayModuleName(int id, const char *line)
888{
889 char filename[12];
890 int i;
891
892 for (i = 0; i < 11 && line[i] >= ' '; i++) {
893 filename[i] = line[i];
894 }
895 filename[i] = '\0';
896
897 DEBUG_PRINTF("%d: %s\n", id, filename);
898}
899#endif
900
901/* 0x000005f4 - this function hates me and I hate it. */
902static void ParseIOPBTCONF(const struct ImageData *ImageDataBuffer, unsigned int NumFiles, const struct RomdirFileStat *stat, struct ResetData *ResetData)
903{
904 unsigned int FilesRemaining, i, NumModules;
905 const char *ptr;
906 char filename_temp[16];
907 struct RomdirFileStat FileStat;
908 struct RomdirFileStat ModuleFileStat;
909 const void **ModList;
910
911 if ((unsigned int)stat->data < (unsigned int)stat->data + stat->romdirent->size) {
912 FilesRemaining = NumFiles - 1;
913 ModList = &ResetData->ModData[ResetData->NumModules];
914 NumModules = 0;
915
916 ptr = stat->data;
917 do {
918 /* 0x00000668 */
919 switch (ptr[0]) {
920 case '@': /* 0x00000670 */
921 ptr++;
922 ResetData->StartAddress = ParseStartAddress(&ptr);
923 break;
924 case '!': /* 0x00000690 */
925 if (strncmp(ptr, "!addr ", 6) == 0) {
926 ptr += 6;
927 ModList[NumModules] = (void *)(((unsigned int)ParseStartAddress(&ptr) << 2) + 1);
928
929 /* 0x000007a8 */
930 ResetData->NumModules++;
931 NumModules++;
932 ModList[NumModules] = NULL;
933 } else if (strncmp(ptr, "!include ", 9) == 0) {
934 ptr += 9;
935
936 i = 0;
937 while ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size) {
938 if (*ptr >= 0x20) {
939 filename_temp[i] = *ptr;
940 ptr++;
941 i++;
942 } else
943 break;
944 }
945 filename_temp[i] = '\0';
946
947 ScanImagesForFile(ImageDataBuffer, FilesRemaining, &FileStat, filename_temp);
948 ParseIOPBTCONF(ImageDataBuffer, FilesRemaining, &FileStat, ResetData);
949 ModList = &ResetData->ModData[ResetData->NumModules];
950
951 /*
952 I have problems seeing why this won't break down if "!include" is used in the middle of a list of modules:
953 Before parsing included IOPBTCONF file:
954 ###_____________
955 | ^
956 After parsing included IOPBTCONF file:
957 ###XXXXXXXX_____
958 | ^ (The pointer would still be offset by 3, wouldn't it?)
959 If 2 additional modules are added to the list of modules:
960 ###XXXXXXXX___XX_
961 | ^ (If I'm not wrong, a gap of 3 would result)
962 Legend:
963 # -> Modules loaded during the first call to ParseIOPBTCONF.
964 X -> Modules loaded when the included IOPBTCONF file is parsed.
965 | -> The base pointer to the start of the module list.
966 ^ -> The pointer to the end of the module list.
967 _ -> Blank module slots.
968
969 $s2 seems to contain a relative pointer which points to the first blank module slot. It seems to be added to the base pointer ($s0) when the module list is accessed.
970 When an included IOPBTCONF file is parsed, $s0 is adjusted but $s2 is not.
971
972 If it's by design, then it will mean that Sony had intended only one additional IOPBTCONF file to be included in each file, and it must be included at only either the absolute start or end of the file.
973 */
974 NumModules = 0; // Therefore, unlike the Sony original, reset the module offset counter.
975 }
976 break;
977 case '#': /* 0x0000077c */
978 break;
979 default: /* 0x00000784 */
980#ifdef DEBUG
981 DisplayModuleName(ResetData->NumModules, ptr); // Code for debugging only - not originally present.
982#endif
983 if (SelectModuleFromImages(ImageDataBuffer, NumFiles, ptr, &ModuleFileStat) == NULL) {
984 __builtin_trap();
985 }
986
987 ModList[NumModules] = ModuleFileStat.data;
988
989 /* 0x000007a8 */
990 ResetData->NumModules++;
991 NumModules++;
992 ModList[NumModules] = NULL;
993 }
994
995 /* 0x000007c0 */
996 if ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size) {
997 while ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size) {
998 if (*ptr >= 0x20) {
999 ptr++;
1000 } else
1001 break;
1002 }
1003 if ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size) {
1004 while ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size) {
1005 if (*ptr < 0x20) {
1006 ptr++;
1007 } else
1008 break;
1009 }
1010 }
1011 }
1012 } while ((unsigned int)ptr < (unsigned int)stat->data + stat->romdirent->size);
1013 }
1014}
1015
1016int _start(int argc, char *argv[])
1017{
1018 int ImageDataTotalSize;
1019#ifdef FULL_UDNL
1020 struct ImageData *ImageData;
1021#endif
1022 struct ImageData *ImageDataBuffer;
1023 void *buffer, *IoprpBuffer;
1024 struct ResetData *ResetData;
1025 int TotalSize;
1026#ifdef FULL_UDNL
1027 int fd, file_sz = 0, i, NumFiles;
1028#endif
1029 struct RomdirFileStat FileStat;
1030
1031#ifdef UDNL_T300
1032 unsigned int BootMode4, BootMode3, options;
1033 void *BootModePtr;
1034 struct RomdirFileStat ROMStat;
1035
1036 BootMode4 = 0xFFFFFFFF;
1037 BootMode3 = 0;
1038 if ((BootModePtr = QueryBootMode(4)) != NULL) {
1039 BootMode4 = *(unsigned char *)BootModePtr;
1040 }
1041 if ((BootModePtr = QueryBootMode(3)) != NULL) {
1042 BootMode3 = *(unsigned int *)((unsigned char *)BootModePtr + 4);
1043 }
1044#endif
1045
1046 /*
1047 Let f(x)=((x+2)*2+(x+2))*8, where x>0
1048 f(1)=((1+2)*2+(1+2))*8=72
1049 f(2)=((2+2)*2+(2+2))*8=96
1050 f(3)=((3+2)*2+(3+2))*8=120
1051
1052 Therefore, each element is 24 bytes long, with an additional 48 bytes extra allocated for the built-in IOPRP images (The boot ROM and the DATA section of the UDNL module).
1053
1054 --- Original disassembly ---
1055 ImageDataTotalSize=((argc+2)<<1);
1056 ImageDataTotalSize=ImageDataTotalSize+(argc+2);
1057 ImageDataTotalSize=(ImageDataTotalSize<<3);
1058
1059 Note: The function reserves an additional 32-bytes of space on the stack when the function enters.
1060 The pointers are then offset by 0x10 bytes.
1061 $s7=$sp+0x10 <- Start of image list buffer.
1062 $s4=$sp+0x40 <- Points to the image entries within the image list buffer.
1063 */
1064 ImageDataTotalSize = (argc + 2) * sizeof(struct ImageData);
1065 ImageDataBuffer = alloca(ImageDataTotalSize);
1066 memset(ImageDataBuffer, 0, ImageDataTotalSize);
1067
1068 TotalSize = MAX_MODULES * sizeof(void *) + sizeof(struct ResetData);
1069#ifdef USE_EMBEDDED_IOPRP
1070 TotalSize += ((size_IOPRP_img + 0xF) & ~0xF); // Unlike the ROM UDNL module, allocate space for the embedded IOPRP image as well like the DVD player UDNL module does.
1071#endif
1072
1073#ifdef FULL_UDNL
1074 i = 1;
1075 NumFiles = 2;
1076 ImageData = &ImageDataBuffer[2];
1077#ifdef UDNL_T300
1078 options = 0;
1079#endif
1080 while (i < argc) {
1081#ifdef UDNL_T300
1082 if (strcmp(argv[i], "-v") == 0) {
1083 var_00001e20++;
1084 }
1085#else
1086 if (strcmp(argv[i], "-v") != 0)
1087#endif
1088#ifdef UDNL_T300
1089 else if (strcmp(argv[i], "-nobusini") == 0 || strcmp(argv[i], "-nb") == 0) {
1090 options |= 1;
1091 } else if (strcmp(argv[i], "-nocacheini") == 0 || strcmp(argv[i], "-nc") == 0) {
1092 options |= 2;
1093 } else
1094#endif
1095 {
1096 /*
1097 if (isIllegalBootDevice(argv[i])) { //This block of commented-out code (and the commented-out isIllegalBootDevice() function) is what all Sony UDNL modules have, to prevent the loading of IOPRP images from unsecured devices.
1098#ifdef UDNL_T300
1099 if (BootMode4 & 2) {
1100 goto end;
1101 }
1102#endif
1103 SleepThread();
1104 __builtin_trap();
1105 }
1106 }
1107 */
1108
1109 if ((fd = open(argv[i], O_RDONLY)) < 0) {
1110#ifdef UDNL_T300
1111 printf("kupdate: pannic ! file \'%s\' can't open\n", argv[i]);
1112#else
1113 printf("file \'%s\' can't open\n", argv[i]);
1114#endif
1115#ifdef UDNL_T300
1116 if (BootMode4 & 2) {
1117 goto end;
1118 }
1119#endif
1120 SleepThread();
1121 __builtin_trap();
1122 }
1123
1124 file_sz = lseek(fd, 0, SEEK_END);
1125 lseek(fd, 0, SEEK_SET);
1126 if (file_sz <= 0) {
1127 close(fd);
1128 break;
1129 } else {
1130 TotalSize += (file_sz + 0xF) & ~0xF;
1131 ImageData->fd = fd;
1132 ImageData->size = file_sz;
1133 ImageData->filename = argv[i];
1134 NumFiles++;
1135 ImageData++;
1136 }
1137 }
1138#ifndef UDNL_T300
1139 else {
1140 var_00001850++;
1141 }
1142#endif
1143
1144 i++;
1145 }
1146#endif
1147
1148 /* 0x000002f8 */
1149 if ((buffer = AllocMemory(TotalSize)) == NULL) {
1150#ifdef UDNL_T300
1151 printf("kupdate: pannic ! can not alloc memory\n");
1152#else
1153 printf("pannic ! can not alloc memory\n");
1154#endif
1155#ifdef UDNL_T300
1156 if (BootMode4 & 2) {
1157 goto end;
1158 }
1159#endif
1160 SleepThread();
1161 __builtin_trap();
1162 }
1163
1164 ResetData = buffer;
1165 memset(ResetData, 0, sizeof(struct ResetData));
1166 ResetData->ModData = (void *)((u8 *)buffer + sizeof(struct ResetData));
1167 IoprpBuffer = (void *)((unsigned int)buffer + MAX_MODULES * sizeof(void *) + sizeof(struct ResetData));
1168 ResetData->IOPRPBuffer = (void *)((unsigned int)IoprpBuffer & 0x1FFFFF00);
1169 ResetData->MemSize = QueryMemSize() >> 20;
1170#ifdef UDNL_T300
1171 if (ResetData->MemSize == 8) {
1172 if (BootMode3 & 0x00000080) {
1173 printf(" Logical memory size 8MB ---> 2MB\n");
1174 ResetData->MemSize = 2;
1175 }
1176 }
1177#endif
1178 ResetData->BootMode = 3;
1179 ResetData->command = NULL;
1180 if (GetIOPRPStat((void *)0xbfc00000, (void *)0xbfc10000, &ImageDataBuffer[0].stat) != NULL) {
1181 ImageDataBuffer[0].filename = "ROM";
1182 }
1183#ifdef UDNL_T300
1184 if (BootMode3 & 0x00000100) {
1185 if (GetFileStatFromImage(&ImageDataBuffer[0].stat, "OLDROM", &ROMStat) != 0 && GetIOPRPStat(ROMStat.data, (const void *)((const u8 *)(ROMStat.data) + 0x40000), &ImageDataBuffer[1].stat)) {
1186 memcpy(&ImageDataBuffer[0].stat, &ImageDataBuffer[1].stat, sizeof(ImageDataBuffer[0].stat));
1187 printf(" use alternate ROM image\n");
1188 }
1189 }
1190#endif
1191 /* 0x00000398 */
1192 /* Originally, the Sony boot ROM UDNL module did this. However, it doesn't work well because the rest of the data used in the reset will go unprotected. The Sony DVD player UDNL modules allocate memory for the embedded IOPRP image and copies the IOPRP image into the buffer, like if it was read in from a file. */
1193#ifdef USE_EMBEDDED_IOPRP
1194#if 0
1195 if (size_IOPRP_img >= 0x10 && GetIOPRPStat(IOPRP_img, &IOPRP_img[size_IOPRP_img], &ImageDataBuffer[1].stat) != NULL) {
1196 ImageDataBuffer[1].filename = "DATA";
1197 ResetData->IOPRPBuffer = (void*)((unsigned int)IOPRP_img & ~0xF);
1198 }
1199#endif
1200 if (size_IOPRP_img >= 0x10) { // Hence, do this instead:
1201 memcpy(IoprpBuffer, IOPRP_img, size_IOPRP_img);
1202 if (GetIOPRPStat(IoprpBuffer, (void *)((unsigned int)IoprpBuffer + size_IOPRP_img), &ImageDataBuffer[1].stat) != NULL) {
1203 ImageDataBuffer[1].filename = "DATA";
1204 IoprpBuffer = (void *)((u8 *)IoprpBuffer + ((size_IOPRP_img + 0xF) & ~0xF));
1205 }
1206 }
1207#endif
1208
1209#ifdef FULL_UDNL
1210 /* 0x000003dc */
1211 i = 2;
1212 if (i < NumFiles) {
1213 ImageData = &ImageDataBuffer[2];
1214
1215 do {
1216 if (read(ImageData->fd, IoprpBuffer, ImageData->size) == ImageData->size) {
1217 if (GetIOPRPStat(IoprpBuffer, (void *)((u8 *)IoprpBuffer + 0x4000), &ImageData->stat) != NULL) {
1218 /* 0x00000420 */
1219 IoprpBuffer = (void *)((u8 *)IoprpBuffer + ((ImageData->size + 0xF) & ~0xF));
1220 }
1221 }
1222#ifdef UDNL_T300
1223 close(ImageData->fd);
1224#endif
1225 i++;
1226 ImageData++;
1227 } while (i < NumFiles);
1228 }
1229#endif
1230
1231 /* 0x00000448 */
1232 ResetData->IOPRPBufferSize = IoprpBuffer - ResetData->IOPRPBuffer + 0x100;
1233#ifdef FULL_UDNL
1234 ScanImagesForFile(ImageDataBuffer, NumFiles, &FileStat, "IOPBTCONF");
1235 ParseIOPBTCONF(ImageDataBuffer, NumFiles, &FileStat, ResetData);
1236#else
1237 ScanImagesForFile(ImageDataBuffer, 2, &FileStat, "IOPBTCONF");
1238 ParseIOPBTCONF(ImageDataBuffer, 2, &FileStat, ResetData);
1239#endif
1240
1241 DEBUG_PRINTF("Beginning IOP bootup sequence.\n");
1242
1243#ifdef UDNL_T300
1244 TerminateResidentLibraries(" kupdate:ei: Terminate resident Libraries\n", options, 2);
1245 CpuExecuteKmode(&BeginBootupSequence, ResetData, options);
1246#else
1248 dmac_set_dpcr(0);
1249 dmac_set_dpcr2(0);
1250 dmac_set_dpcr3(0);
1251 BeginBootupSequence(ResetData);
1252#endif
1253
1254#ifdef UDNL_T300
1255end:
1256 return MODULE_NO_RESIDENT_END;
1257#else
1258 return MODULE_RESIDENT_END;
1259#endif
1260}
1261
1262/* 0x000004cc */
1263static void *AllocMemory(int nbytes)
1264{
1265 void *BlockTopAddress;
1266 int result;
1267
1268 BlockTopAddress = QueryBlockTopAddress((void *)0x1860);
1269 BlockTopAddress = (void *)((unsigned int)BlockTopAddress & 0x7FFFFFFF);
1270 do {
1271 while ((result = QueryBlockSize(BlockTopAddress)) >= 0 || (result & 0x7FFFFFFF) < nbytes) {
1272 BlockTopAddress = QueryBlockTopAddress((void *)(((unsigned int)BlockTopAddress & 0x7FFFFFFF) + (result & 0x7FFFFFFF)));
1273 BlockTopAddress = (void *)((unsigned int)BlockTopAddress & 0x7FFFFFFF);
1274 }
1275 } while ((result & 0x7FFFFFFF) < nbytes);
1276
1277 return AllocSysMemory(2, nbytes, BlockTopAddress);
1278}
int CpuDisableIntr()
Definition intrman.c:228
struct tag_LC_internals lc_internals_t
#define COP0_REG_PRId
Definition main.c:20
u32 count
start sector of fragmented bd/file