/** * Parse mbr for filesystem */ void mount_all_devices() { FindPartitions(DEVICE_USB); if (xenon_ata_ops.isInserted()) { XTAFMount(); FindPartitions(DEVICE_ATA); } if (xenon_atapi_ops.isInserted()) { FindPartitions(DEVICE_ATAPI); } }
void Close_USB() { fatUnmount("usb"); if (isUSB2) { __io_usbstorage2.shutdown(); } else { __io_usbstorage.shutdown(); } }
s32 Fat_UnmountSDHC(void) { s32 ret; /* Unmount device */ fatUnmount(SDHC_MOUNT); /* Shutdown SDHC interface */ ret = __io_sdhc.shutdown(); if (!ret) return -1; return 0; }
void Init_USB() { //Close_USB(); printf("\n"); if (AHBPROT_DISABLED && !USB_PORT_CONNECTED) { USBmnt = false; } else { bool started = false; isUSB2 = (IOS_GetVersion() >= 200); time_t tStart = time(0); while ((time(0) - tStart) < 10) // 10 seconds timeout { Con_ClearLine(); printf("\t- USB drive: %.f...", difftime(time(0), tStart)); if (isUSB2) { started = (__io_usbstorage2.startup() && __io_usbstorage2.isInserted()); } else { started = (__io_usbstorage.startup() && __io_usbstorage.isInserted()); } if (started) break; usleep(50000); } USBmnt = (started && fatMountSimple("usb", (isUSB2 ? &__io_usbstorage2 : &__io_usbstorage))); Con_ClearLine(); } printf("\t- USB drive: %s.\n\n", (USBmnt ? "OK" : "FAILED")); }
s32 Init_USB() { if (!__io_usbstorage.startup()) { printf("USB storage error, press any button to exit...\n"); return -1; } if (!fatMountSimple("usb", &__io_usbstorage)) { printf("FAT error, press any button to exit...\n"); return -1; } return 0; }
s32 Fat_MountSDHC(void) { s32 ret; /* Initialize SDHC interface */ ret = __io_sdhc.startup(); if (!ret) return -1; /* Mount device */ ret = fatMountSimple(SDHC_MOUNT, &__io_sdhc); if (!ret) return -2; return 0; }
static int FindPartitions(int device) { int i; int devnum = 0; // clear list for (i = 0; i < MAX_DEVICES; i++) { part[device][i].name[0] = 0; part[device][i].mount[0] = 0; part[device][i].sector = 0; part[device][i].interface = NULL; part[device][i].type = 0; } DISC_INTERFACE *interface; switch(device){ case DEVICE_ATAPI: interface = (DISC_INTERFACE *) & xenon_atapi_ops; break; case DEVICE_ATA: interface = (DISC_INTERFACE *) & xenon_ata_ops; break; case DEVICE_USB: interface = (DISC_INTERFACE *) & usb2mass_ops; break; } MASTER_BOOT_RECORD mbr; PARTITION_RECORD *partition = NULL; devnum = 0; sec_t part_lba = 0; union { u8 buffer[BYTES_PER_SECTOR]; MASTER_BOOT_RECORD mbr; EXTENDED_BOOT_RECORD ebr; NTFS_BOOT_SECTOR boot; } sector; if(device == DEVICE_ATAPI){ AddPartition(0, device, T_ISO9660, &devnum); return devnum; } // Read the first sector on the device if (!interface->readSectors(0, 1, §or.buffer)) { //errno = EIO; return -1; } // If this is the devices master boot record debug_printf("0x%x\n", sector.mbr.signature); if (sector.mbr.signature == MBR_SIGNATURE) { memcpy(&mbr, §or, sizeof (MASTER_BOOT_RECORD)); debug_printf("Valid Master Boot Record found\n"); // Search the partition table for all partitions (max. 4 primary partitions) for (i = 0; i < 4; i++) { partition = &mbr.partitions[i]; part_lba = le32_to_cpu(mbr.partitions[i].lba_start); debug_printf( "Partition %i: %s, sector %u, type 0x%x\n", i + 1, partition->status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", part_lba, partition->type); // Figure out what type of partition this is switch (partition->type) { // NTFS partition case PARTITION_TYPE_NTFS: { debug_printf("Partition %i: Claims to be NTFS\n", i + 1); // Read and validate the NTFS partition if (interface->readSectors(part_lba, 1, §or)) { debug_printf("sector.boot.oem_id: 0x%x\n", sector.boot.oem_id); debug_printf("NTFS_OEM_ID: 0x%x\n", NTFS_OEM_ID); if (sector.boot.oem_id == NTFS_OEM_ID) { debug_printf("Partition %i: Valid NTFS boot sector found\n", i + 1); AddPartition(part_lba, device, T_NTFS, &devnum); } else { debug_printf("Partition %i: Invalid NTFS boot sector, not actually NTFS\n", i + 1); } } break; } // DOS 3.3+ or Windows 95 extended partition case PARTITION_TYPE_DOS33_EXTENDED: case PARTITION_TYPE_WIN95_EXTENDED: { debug_printf("Partition %i: Claims to be Extended\n", i + 1); // Walk the extended partition chain, finding all NTFS partitions within it sec_t ebr_lba = part_lba; sec_t next_erb_lba = 0; do { // Read and validate the extended boot record if (interface->readSectors(ebr_lba + next_erb_lba, 1, §or)) { if (sector.ebr.signature == EBR_SIGNATURE) { debug_printf( "Logical Partition @ %d: %s type 0x%x\n", ebr_lba + next_erb_lba, sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", sector.ebr.partition.type); // Get the start sector of the current partition // and the next extended boot record in the chain part_lba = ebr_lba + next_erb_lba + le32_to_cpu( sector.ebr.partition.lba_start); next_erb_lba = le32_to_cpu( sector.ebr.next_ebr.lba_start); if (sector.ebr.partition.type == PARTITION_TYPE_LINUX) { debug_printf("Partition : type ext2/3/4 found\n"); AddPartition(part_lba, device, T_EXT2, &devnum); }// Check if this partition has a valid NTFS boot record else if (interface->readSectors(part_lba, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { debug_printf( "Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba); if (sector.ebr.partition.type != PARTITION_TYPE_NTFS) { debug_printf( "Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS); } AddPartition(part_lba, device, T_NTFS, &devnum); } else if (!memcmp(sector.buffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof (FAT_SIG)) || !memcmp( sector.buffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof (FAT_SIG))) { debug_printf("Partition : Valid FAT boot sector found\n"); AddPartition(part_lba, device, T_FAT, &devnum); } } } else { next_erb_lba = 0; } } } while (next_erb_lba); break; } case PARTITION_TYPE_LINUX: { debug_printf("Partition %i: Claims to be LINUX\n", i + 1); // Read and validate the EXT2 partition AddPartition(part_lba, device, T_EXT2, &devnum); break; } // Ignore empty partitions case PARTITION_TYPE_EMPTY: debug_printf("Partition %i: Claims to be empty\n", i + 1); // Unknown or unsupported partition type default: { // Check if this partition has a valid NTFS boot record anyway, // it might be misrepresented due to a lazy partition editor if (interface->readSectors(part_lba, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { debug_printf("Partition %i: Valid NTFS boot sector found\n", i + 1); if (partition->type != PARTITION_TYPE_NTFS) { debug_printf( "Partition %i: Is NTFS but type is 0x%x; 0x%x was expected\n", i + 1, partition->type, PARTITION_TYPE_NTFS); } AddPartition(part_lba, device, T_NTFS, &devnum); } else if (!memcmp(sector.buffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof (FAT_SIG)) || !memcmp( sector.buffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof (FAT_SIG))) { debug_printf("Partition : Valid FAT boot sector found\n"); AddPartition(part_lba, device, T_FAT, &devnum); } else { debug_printf("Trying : ext partition\n"); AddPartition(part_lba, device, T_EXT2, &devnum); } } break; } } } } if (devnum == 0) // it is assumed this device has no master boot record or no partitions found { debug_printf("No Master Boot Record was found or no partitions found!\n"); // As a last-ditched effort, search the first 64 sectors of the device for stray NTFS/FAT partitions for (i = 0; i < 64; i++) { if (interface->readSectors(i, 1, §or)) { if (sector.boot.oem_id == NTFS_OEM_ID) { debug_printf("Valid NTFS boot sector found at sector %d!\n", i); AddPartition(i, device, T_NTFS, &devnum); break; } else if (!memcmp(sector.buffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof (FAT_SIG)) || !memcmp(sector.buffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof (FAT_SIG))) { debug_printf("Partition : Valid FAT boot sector found\n"); AddPartition(i, device, T_FAT, &devnum); break; } else { debug_printf("Trying : ext partition\n"); AddPartition(part_lba, device, T_EXT2, &devnum); } } } } return devnum; }
int main(void) { int fd,n,mounted=0; int inited=0; ipcmessage* message; memset(&my_reent, 0, sizeof(struct _reent)); memset(my_filestr, 0, sizeof(FILE_STRUCT)*5); memset(file_table, 0, 4*2*5); memset(&dir_state_internal,0,sizeof(DIR_STATE_STRUCT)); dir_internal.device=0; dir_internal.dirStruct=&dir_state_internal; heaphandle = os_heap_create(heapspace, sizeof(heapspace)); void* queuespace = os_heap_alloc(heaphandle, 0x20); queuehandle = os_message_queue_create(queuespace, 8); void* timer1_queuespace = os_heap_alloc(heaphandle, 0x40); timer1_queuehandle = os_message_queue_create(timer1_queuespace, 16); timer1_id=os_create_timer(1000*1000, 1, timer1_queuehandle, 0x666); os_stop_timer(timer1_id); extern DISC_INTERFACE __io_wiisd; inited=__io_wiisd.startup(); msleep(100); os_device_register(DEVICE, queuehandle); while(1) { int result = 1; int ack = 1; os_message_queue_receive(queuehandle,(void *) &message, 0); switch( message->command ) { case IOS_OPEN: { result = -6; //debug_printf("%s try open %sfor fd %d\n",DEVICE,message->open.device,message->open.resultfd); // Checking device name if (0 == strcmp(message->open.device, DEVICE)) { result = message->open.resultfd; } else if (0 == strcmp(message->open.device, DEVICE"/log")) { if(inited && !mounted) mounted=fatMountSimple("sd", &__io_wiisd); if(mounted) { static char log_name[]="sd:/log000.txt"; for(n=0;n<5;n++) if(my_filestr[n].inUse==0) break; fd=-1; if(n!=5) { my_reent._errno=0; fd=_FAT_open_r(&my_reent, &my_filestr[n], log_name, O_CREAT | O_TRUNC | O_RDWR, 0); log_name[9]++; if(log_name[9]>='9') {log_name[9]='0';log_name[8]++;} if(log_name[8]>='9') {log_name[8]='0';log_name[7]++;} if(log_name[7]>='9') {log_name[7]='0';log_name[8]='0';log_name[9]='0';} } if(fd<0) result=-1; else { result=file_table[n][0]=message->open.resultfd; file_table[n][1]= fd; } } } else if (0 == memcmp(message->open.device, DEVICE"/", sizeof(DEVICE))) { if(inited && !mounted) mounted=fatMountSimple("sd", &__io_wiisd); if(mounted) { for(n=0;n<5;n++) if(my_filestr[n].inUse==0) break; fd=-1; if(n!=5) { my_reent._errno=0; fd=_FAT_open_r(&my_reent, &my_filestr[n], message->open.device+sizeof(DEVICE), message->open.mode, 0); } if(fd<0) result=-1; else { result=file_table[n][0]=message->open.resultfd; file_table[n][1]= fd; } } } } break; case IOS_IOCTLV: { result = -1; ioctlv *vec = message->ioctlv.vector; int i,in = message->ioctlv.num_in,io= message->ioctlv.num_io; os_sync_before_read( vec, (in+io)*sizeof(ioctlv)); for(i=0;i<in+io;i++){ os_sync_before_read( vec[i].data, vec[i].len); } #if 0 // list the directory content to directory.txt switch(message->ioctl.command ) { case 0xcacafea: if(inited && !mounted) mounted=fatMountSimple("sd", &__io_wiisd); if(mounted) { my_reent._errno=0; result=-666; if(_FAT_diropen_r(&my_reent, &dir_internal, "sd:/")) { static char log_name2[]="sd:/directory.txt"; char filename[768]; result = 0; my_reent._errno=0; fd=_FAT_open_r(&my_reent, &my_filestr[4], log_name2, O_CREAT | O_TRUNC | O_RDWR, 0); my_reent._errno=0; while(!_FAT_dirnext_r (&my_reent, &dir_internal, filename, &filestat)) { my_reent._errno=0; if(fd>=0) { if(filestat.st_mode & S_IFDIR)_FAT_write_r (&my_reent, fd, "[", 1); // es directorio _FAT_write_r (&my_reent, fd, filename, strlen(filename)); if(filestat.st_mode & S_IFDIR)_FAT_write_r (&my_reent, fd, "]", 1); // es directorio _FAT_write_r (&my_reent, fd, "\n", 1); } } my_reent._errno=0; if(fd>=0) _FAT_close_r (&my_reent, fd);fd=-1; _FAT_dirclose_r(&my_reent, &dir_internal); } } break; } #endif for(i=in;i<in+io;i++){ os_sync_after_write( vec[i].data, vec[i].len); } } break; case IOS_CLOSE: { result = -1; if(mounted) { my_reent._errno=0; for(n=0;n<5;n++) { if(message->fd==file_table[n][0]) { fd=file_table[n][1]; file_table[n][0]=file_table[n][1]=0; _FAT_close_r (&my_reent, fd); result = 0; break; } } for(n=0;n<5;n++) if(my_filestr[n].inUse!=0) break; if(n==5) {fatUnmount ("sd");mounted=0;} } else result=-6; } break; case IOS_READ: { result=-1; if(mounted) { my_reent._errno=0; for(n=0;n<5;n++) { if(message->fd==file_table[n][0]) { fd=file_table[n][1]; result=_FAT_read_r (&my_reent, fd, message->write.data, message->write.length); } } } os_sync_after_write( message->write.data, message->write.length); } break; case IOS_WRITE: { os_sync_before_read( message->write.data, message->write.length); result=-1; if(mounted) { my_reent._errno=0; for(n=0;n<5;n++) { if(message->fd==file_table[n][0]) { fd=file_table[n][1]; result=_FAT_write_r (&my_reent, fd, message->write.data, message->write.length); } } } } break; case IOS_SEEK: { result=-1; if(mounted) { my_reent._errno=0; for(n=0;n<5;n++) { if(message->fd==file_table[n][0]) { fd=file_table[n][1]; result=_FAT_seek_r (&my_reent, fd, message->seek.offset, message->seek.origin); } } } } break; default: result=-1; break; } if (ack) os_message_queue_ack( (void*)message, result ); } return 0; }
int main(int argc, char **argv) { // Exit after 10 seconds if there is an error __exception_setreload(10); // u64 timeout = 0; CheckForGecko(); DCInvalidateRange(loader_stub, 0x1800); memcpy(loader_stub, (void*)0x80001800, 0x1800); RAMInit(); //Meh, doesnt do anything anymore anyways //STM_RegisterEventHandler(HandleSTMEvent); Initialise(); // Checking for storage devices... ShowMessageScreen("Checking storage devices..."); u32 u; //Disables MEMPROT for patches write16(MEM_PROT, 0); //Patches FS access for( u = 0x93A00000; u < 0x94000000; u+=2 ) { if( memcmp( (void*)(u), FSAccessPattern, sizeof(FSAccessPattern) ) == 0 ) { // gprintf("FSAccessPatch:%08X\r\n", u ); memcpy( (void*)u, FSAccessPatch, sizeof(FSAccessPatch) ); DCFlushRange((void*)u, sizeof(FSAccessPatch)); break; } } //for BT.c CONF_GetPadDevices((conf_pads*)0x932C0000); DCFlushRange((void*)0x932C0000, sizeof(conf_pads)); *(vu32*)0x932C0490 = CONF_GetIRSensitivity(); *(vu32*)0x932C0494 = CONF_GetSensorBarPosition(); DCFlushRange((void*)0x932C0490, 8); if(LoadKernel() < 0) { ClearScreen(); gprintf("Failed to load kernel from NAND!\r\n"); ShowMessageScreenAndExit("Failed to load kernel from NAND!", 1); } InsertModule((char*)kernel_bin, kernel_bin_size); memset( (void*)0x92f00000, 0, 0x100000 ); DCFlushRange( (void*)0x92f00000, 0x100000 ); DCInvalidateRange( (void*)0x939F02F0, 0x20 ); memcpy( (void*)0x939F02F0, Boot2Patch, sizeof(Boot2Patch) ); DCFlushRange( (void*)0x939F02F0, 0x20 ); //libogc still has that, lets close it __ES_Close(); s32 fd = IOS_Open( "/dev/es", 0 ); memset( STATUS, 0xFFFFFFFF, 0x20 ); DCFlushRange( STATUS, 0x20 ); memset( (void*)0x91000000, 0xFFFFFFFF, 0x20 ); DCFlushRange( (void*)0x91000000, 0x20 ); *(vu32*)0xD3003420 = 0; //make sure kernel doesnt reload raw_irq_handler_t irq_handler = BeforeIOSReload(); IOS_IoctlvAsync( fd, 0x1F, 0, 0, &IOCTL_Buf, NULL, NULL ); AfterIOSReload( irq_handler, FoundVersion ); while(1) { DCInvalidateRange( STATUS, 0x20 ); if((STATUS_LOADING > 0 || abs(STATUS_LOADING) > 1) && STATUS_LOADING < 20) { gprintf("Kernel sent signal\n"); break; } } /* For slow USB HDDs */ time_t timeout = time(NULL); while(time(NULL) - timeout < 10) { if(__io_custom_usbstorage.startup() && __io_custom_usbstorage.isInserted()) break; usleep(50000); } fatInitDefault(); gprintf("Nintendont at your service!\r\n%s\r\n", NIN_BUILD_STRING); KernelLoaded = 1; char* first_slash = strrchr(argv[0], '/'); if (first_slash != NULL) strncpy(launch_dir, argv[0], first_slash-argv[0]+1); gprintf("launch_dir = %s\r\n", launch_dir); FPAD_Init(); FPAD_Update(); /* Read IPL Font before doing any patches */ void *fontbuffer = memalign(32, 0x50000); __SYS_ReadROM((void*)fontbuffer,0x50000,0x1AFF00); memcpy((void*)0xD3100000, fontbuffer, 0x50000); DCInvalidateRange( (void*)0x93100000, 0x50000 ); free(fontbuffer); //gprintf("Font: 0x1AFF00 starts with %.4s, 0x1FCF00 with %.4s\n", (char*)0x93100000, (char*)0x93100000 + 0x4D000); // Simple code to autoupdate the meta.xml in Nintendont's folder FILE *meta = fopen("meta.xml", "w"); if(meta != NULL) { fprintf(meta, "%s\r\n<app version=\"1\">\r\n\t<name>%s</name>\r\n", META_XML, META_NAME); fprintf(meta, "\t<coder>%s</coder>\r\n\t<version>%d.%d</version>\r\n", META_AUTHOR, NIN_VERSION>>16, NIN_VERSION&0xFFFF); fprintf(meta, "\t<release_date>20150531000000</release_date>\r\n"); fprintf(meta, "\t<short_description>%s</short_description>\r\n", META_SHORT); fprintf(meta, "\t<long_description>%s\r\n\r\n%s</long_description>\r\n", META_LONG1, META_LONG2); fprintf(meta, "\t<ahb_access/>\r\n</app>"); fclose(meta); }
int isInserted(const char *path) { if (!strncmp(path, "USB:", 4)) return 1; return __io_sdhc.isInserted() || __io_wiisd.isInserted(); }