s32 Partition_GetEntries(u32 device, partitionEntry *outbuf, u32 *outval) { static partitionTable table ATTRIBUTE_ALIGN(32); u32 cnt, sector_size; s32 ret; /* Read from specified device */ switch (device) { case WBFS_DEVICE_USB: { /* Get sector size */ ret = USBStorage_GetCapacity(§or_size); if (ret == 0) return -1; /* Read partition table */ u8* table_buf = memalign(32, sector_size); ret = USBStorage_ReadSectors(0, 1, table_buf); memcpy(&table, table_buf, sizeof(table)); SAFE_FREE(table_buf); if (ret < 0) return ret; break; } case WBFS_DEVICE_SDHC: { /* SDHC sector size */ sector_size = SDHC_SECTOR_SIZE; /* Read partition table */ ret = SDHC_ReadSectors(0, 1, &table); if (!ret) return -1; break; } default: return -1; } /* Swap endianess */ for (cnt = 0; cnt < 4; cnt++) { partitionEntry *entry = &table.entries[cnt]; entry->sector = swap32(entry->sector); entry->size = swap32(entry->size); } /* Set partition entries */ memcpy(outbuf, table.entries, sizeof(table.entries)); /* Set sector size */ *outval = sector_size; return 0; }
s32 WBFS_Init(u32 device, u32 timeout) { u32 cnt; s32 ret; /* Wrong timeout */ if (!timeout) return -1; /* Try to mount device */ for (cnt = 0; cnt < timeout; cnt++) { switch (device) { case WBFS_DEVICE_USB: { /* Initialize USB storage */ ret = USBStorage_Init(); if (ret >= 0) { /* Setup callbacks */ readCallback = __WBFS_ReadUSB; writeCallback = __WBFS_WriteUSB; /* Device info */ nb_sectors = USBStorage_GetCapacity(§or_size); goto out; } } case WBFS_DEVICE_SDHC: { /* Initialize SDHC */ ret = SDHC_Init(); if (ret) { /* Setup callbacks */ readCallback = __WBFS_ReadSDHC; writeCallback = __WBFS_WriteSDHC; /* Device info */ nb_sectors = 0; sector_size = SDHC_SECTOR_SIZE; goto out; } else ret = -1; } default: return -1; } /* Sleep 1 second */ sleep(1); } out: return ret; }
s32 Partition_GetEntriesEx(u32 device, partitionEntry *outbuf, u32 *psect_size, int *num) { static union { u8 buf[4096]; partitionTable table; wbfs_head_t head; } tbl ATTRIBUTE_ALIGN(32); partitionTable *table = &tbl.table; partitionEntry *entry; u32 i, sector_size; s32 ret; int maxpart = *num; int is_raw = 0; // Get sector size switch (device) { case WBFS_DEVICE_USB: ret = USBStorage_GetCapacity(§or_size); if (ret == 0) return -1; break; case WBFS_DEVICE_SDHC: sector_size = SDHC_SECTOR_SIZE; break; default: return -1; } /* Set sector size */ *psect_size = sector_size; if (sector_size < 512 || sector_size > 4096) { printf("ERROR: sector size: %u\n", sector_size); sleep(5); return -2; } u32 ext = 0; u32 next = 0; // Read partition table ret = Device_ReadSectors(device, 0, 1, tbl.buf); if (!ret) return -1; // Check if it's a RAW FS disc, without partition table ret = get_fs_type(table); dbg_printf("fstype(%d)=%d\n", device, ret); if (ret != PART_FS_UNK) { // looks like a raw fs if (!is_valid_ptable(table)) { // if invalid part. table then yes it's raw is_raw = 1; } else { dbg_printf("WARNING: ambiguous part.table!\n", ret); // ambiguous: looks like a raw fs and a valid part. table // make a decision based on device type // sd: assume raw; usb: assume part. table if (device == WBFS_DEVICE_SDHC) { is_raw = 1; } } } if (is_raw) { dbg_printf("RAW\n", ret); memset(outbuf, 0, sizeof(table->entries)); // create a fake partition entry if (ret == PART_FS_WBFS) { wbfs_head_t *head = &tbl.head; outbuf->size = wbfs_ntohl(head->n_hd_sec); } else { outbuf->size = 1; } if (ret == PART_FS_NTFS) { outbuf->type = 0x07; } else { outbuf->type = 0x0b; } *num = 1; return 0; } /* Swap endianess */ for (i = 0; i < 4; i++) { entry = &table->entries[i]; entry->sector = swap32(entry->sector); entry->size = swap32(entry->size); if (!ext && part_is_extended(entry->type)) { ext = entry->sector; } } /* Set partition entries */ memcpy(outbuf, table->entries, sizeof(table->entries)); // num primary *num = 4; if (!ext) return 0; next = ext; // scan extended partition for logical for(i=0; i<maxpart-4; i++) { ret = Device_ReadSectors(device, next, 1, tbl.buf); if (!ret) break; if (i == 0) { // handle the invalid scenario where wbfs is on an EXTENDED // partition instead of on the Logical inside Extended. if (get_fs_type(table) == PART_FS_WBFS) break; } entry = &table->entries[0]; entry->sector = swap32(entry->sector); entry->size = swap32(entry->size); if (entry->type && entry->size && entry->sector) { // rebase to abolute address entry->sector += next; // add logical memcpy(&outbuf[*num], entry, sizeof(*entry)); (*num)++; // get next entry++; if (entry->type && entry->size && entry->sector) { next = ext + swap32(entry->sector); } else { break; } } } return 0; }
s32 WBFS_Init_Dev(u32 device) { s32 ret = -1; if (wbfs_disc_mutex == LWP_MUTEX_NULL) { LWP_MutexInit(&wbfs_disc_mutex, true); } /* Try to mount device */ switch (device) { case WBFS_DEVICE_USB: { long long t1 = TIME_D(usb_init); long long t2; get_time(&TIME.usb_retry1); /* Initialize USB storage */ ret = USBStorage_Init(); if (ret >= 0) { /* Setup callbacks */ readCallback = __WBFS_ReadUSB; writeCallback = __WBFS_WriteUSB; /* Device info */ nb_sectors = USBStorage_GetCapacity(&wbfs_dev_sector_size); get_time(&TIME.usb_retry2); t2 = TIME_D(usb_init); TIME.usb_retry2 -= (t2 - t1); goto out; } } break; case WBFS_DEVICE_SDHC: { /* Initialize SDHC */ ret = SDHC_Init(); // returns true=ok false=error if (!ret && !sdhc_mode_sd) { // try normal SD sdhc_mode_sd = 1; ret = SDHC_Init(); } if (ret) { /* Setup callbacks */ readCallback = __WBFS_ReadSDHC; writeCallback = __WBFS_WriteSDHC; /* Device info */ nb_sectors = 0; wbfs_dev_sector_size = SDHC_SECTOR_SIZE; goto out; } ret = -1; } break; default: return -1; } out: return ret; }