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