PS2SDK
PS2 Homebrew Libraries
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 
16 IRX_ID(MODNAME, 1, 1);
17 
18 #ifdef UDNL_T300
19 int 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
35 static void CopySection(const void *module, void *buffer, unsigned int FileSize);
36 static void *AllocMemory(int nbytes);
37 
38 #ifdef FULL_UDNL
39 /* Evil function. */
40 /* 0x00000000 */
41 /*
42 int 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 
90 end_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 
106 struct 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
120 static int var_00001e20 = 0; /* 0x00001e20 - Not sure what this is, but it's probably a verbosity level flag, although unused. */
121 #else
122 static 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
127 extern unsigned char IOPRP_img[];
128 extern unsigned int size_IOPRP_img;
129 #endif
130 
131 struct RomImgData
132 { /* 12 bytes */
133  const void *ImageStart;
134  const void *RomdirStart;
135  const void *RomdirEnd;
136 };
137 
138 struct ImageData
139 { /* 24 bytes */
140  const char *filename;
141  int fd;
142  int size;
143  struct RomImgData stat;
144 };
145 
146 struct RomDirEntry
147 {
148  char name[10];
149  unsigned short int ExtInfoEntrySize;
150  unsigned int size;
151 };
152 
153 /* 0x00001220 */
154 static 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 
179 struct RomdirFileStat
180 {
181  const struct RomDirEntry *romdirent;
182  const void *data;
183  const void *extinfo;
184  unsigned int padding;
185 };
186 
187 /* 0x000012c8 */
188 static 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
246 end:
247  return result;
248 #else
249  return NULL;
250 #endif
251 }
252 
253 /* 0x0000055c */
254 static 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
295 static 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 
332 struct ssbus_regs
333 {
334  volatile unsigned int *address, *delay;
335 };
336 
337 static 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
355 static 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
370 void func_00001b38(unsigned int arg1);
371 
372 // 0x00000c98
373 static 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
413 void func_00001930(void);
414 #else
415 void func_00001440(void);
416 #endif
417 
418 enum 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 */
426 static 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 */
488 static 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 */
505 static 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 */
515 static 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 */
531 static 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 */
554 static 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 
626 struct ModInfo
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. */
645 static 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 */
667 static 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
691 static void BeginBootupSequence(struct ResetData *ResetData, unsigned int options)
692 #else
693 static 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 */
763 static 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 */
798 static 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. */
824 static 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
887 static 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. */
902 static 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 
1016 int _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
1247  CpuDisableIntr();
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
1255 end:
1256  return MODULE_NO_RESIDENT_END;
1257 #else
1258  return MODULE_RESIDENT_END;
1259 #endif
1260 }
1261 
1262 /* 0x000004cc */
1263 static 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 }
RomDirEntry
Definition: romdrv.h:39
CpuDisableIntr
int CpuDisableIntr()
Definition: intrman.c:228
dmacman.h
iopmod_id
Definition: ELF.h:101
thbase.h
elf_pheader_t
Definition: elf.h:38
sysclib.h
scnhdr
Definition: loadcore.c:174
elf_rel
Definition: loadcore.c:71
mipscopaccess.h
coff_filehdr
Definition: loadcore.c:138
loadcore.h
_iop_library
Definition: loadcore.h:68
ModInfo
Definition: udnl.c:626
ExtInfoField
Definition: udnl.c:791
ImageData
Definition: udnl.c:138
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
ResetData
Definition: loadcore.c:238
stdio.h
aouthdr
Definition: loadcore.c:154
elf_shdr_t
Definition: loadcore.c:57
ioman.h
iopmod
Definition: loadcore.c:125
tag_LC_internals
Definition: loadcore.h:78
sysmem.h
ModuleInfo
Definition: udnl.c:398
COP0_REG_PRId
@ COP0_REG_PRId
Definition: mipscopaccess.h:42
ssbus_regs
Definition: modload.c:1998
RomImgData
Definition: igreeting.c:17
intrman.h
RomdirFileStat
Definition: romdrv.c:26
elf_header_t
Definition: elf.h:20