libwbfs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851
  1. // Copyright 2009 Kwiirk
  2. // Licensed under the terms of the GNU GPL, version 2
  3. // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
  4. #include "libwbfs.h"
  5. #include <errno.h>
  6. #ifndef WIN32
  7. #define likely(x) __builtin_expect(!!(x), 1)
  8. #define unlikely(x) __builtin_expect(!!(x), 0)
  9. #else
  10. #define likely(x) (x)
  11. #define unlikely(x) (x)
  12. #endif
  13. #define WBFS_GOTO_ERROR(x) do {wbfs_error(x);goto error;}while(0)
  14. #define ALIGN_LBA(x) (((x)+p->hd_sec_sz-1)&(~(p->hd_sec_sz-1)))
  15. static int force_mode=0;
  16. void wbfs_set_force_mode(int force)
  17. {
  18. force_mode = force;
  19. }
  20. static u8 size_to_shift(u32 size)
  21. {
  22. u8 ret = 0;
  23. while (size)
  24. {
  25. ret++;
  26. size>>=1;
  27. }
  28. return ret-1;
  29. }
  30. #define read_le32_unaligned(x) ((x)[0]|((x)[1]<<8)|((x)[2]<<16)|((x)[3]<<24))
  31. void wbfs_sync(wbfs_t*p);
  32. wbfs_t*wbfs_open_hd(
  33. rw_sector_callback_t read_hdsector,
  34. rw_sector_callback_t write_hdsector,
  35. #ifdef WIN32
  36. close_callback_t close_hd,
  37. #endif
  38. void *callback_data,
  39. int hd_sector_size,
  40. #ifdef WIN32
  41. int num_hd_sector,
  42. #else
  43. int num_hd_sector __attribute((unused)),
  44. #endif
  45. int reset)
  46. {
  47. int i
  48. #ifdef UNUSED_STUFF
  49. = num_hd_sector
  50. #endif
  51. , ret;
  52. u8 *ptr,*tmp_buffer = wbfs_ioalloc(hd_sector_size);
  53. u8 part_table[16*4];
  54. ret = read_hdsector(callback_data,0,1,tmp_buffer);
  55. if(ret)
  56. return 0;
  57. //find wbfs partition
  58. wbfs_memcpy(part_table,tmp_buffer+0x1be,16*4);
  59. ptr = part_table;
  60. for(i=0;i<4;i++,ptr+=16)
  61. {
  62. u32 part_lba = read_le32_unaligned(ptr+0x8);
  63. wbfs_head_t *head = (wbfs_head_t *)tmp_buffer;
  64. #ifdef UNUSED_STUFF
  65. ret =
  66. #endif
  67. read_hdsector(callback_data,part_lba,1,tmp_buffer);
  68. // verify there is the magic.
  69. if (head->magic == wbfs_htonl(WBFS_MAGIC))
  70. {
  71. wbfs_t *p = wbfs_open_partition( read_hdsector,
  72. write_hdsector,
  73. #ifdef WIN32
  74. close_hd,
  75. #endif
  76. callback_data,
  77. hd_sector_size,
  78. 0,
  79. part_lba,reset
  80. );
  81. return p;
  82. }
  83. }
  84. if(reset)// XXX make a empty hd partition..
  85. {
  86. }
  87. return 0;
  88. }
  89. wbfs_t*wbfs_open_partition(rw_sector_callback_t read_hdsector,
  90. rw_sector_callback_t write_hdsector,
  91. #ifdef WIN32
  92. close_callback_t close_hd,
  93. #endif
  94. void *callback_data,
  95. int hd_sector_size, int num_hd_sector, u32 part_lba, int reset)
  96. {
  97. wbfs_t *p = wbfs_malloc(sizeof(wbfs_t));
  98. wbfs_head_t *head = wbfs_ioalloc(hd_sector_size?hd_sector_size:512);
  99. //constants, but put here for consistancy
  100. p->wii_sec_sz = 0x8000;
  101. p->wii_sec_sz_s = size_to_shift(0x8000);
  102. p->n_wii_sec = (num_hd_sector/0x8000)*hd_sector_size;
  103. p->n_wii_sec_per_disc = 143432*2;//support for double layers discs..
  104. p->head = head;
  105. p->part_lba = part_lba;
  106. // init the partition
  107. if (reset)
  108. {
  109. u8 sz_s;
  110. wbfs_memset(head,0,hd_sector_size);
  111. head->magic = wbfs_htonl(WBFS_MAGIC);
  112. head->hd_sec_sz_s = size_to_shift(hd_sector_size);
  113. head->n_hd_sec = wbfs_htonl(num_hd_sector);
  114. // choose minimum wblk_sz that fits this partition size
  115. for(sz_s=6;sz_s<11;sz_s++)
  116. {
  117. // ensure that wbfs_sec_sz is big enough to address every blocks using 16 bits
  118. if(p->n_wii_sec <((1U<<16)*(1<<sz_s)))
  119. break;
  120. }
  121. head->wbfs_sec_sz_s = sz_s+p->wii_sec_sz_s;
  122. } else
  123. read_hdsector(callback_data,p->part_lba,1,head);
  124. if (head->magic != wbfs_htonl(WBFS_MAGIC))
  125. WBFS_GOTO_ERROR("bad magic");
  126. if(!force_mode && hd_sector_size && head->hd_sec_sz_s != size_to_shift(hd_sector_size))
  127. WBFS_GOTO_ERROR("hd sector size doesn't match");
  128. if(!force_mode && num_hd_sector && head->n_hd_sec != wbfs_htonl(num_hd_sector))
  129. WBFS_GOTO_ERROR("hd num sector doesn't match");
  130. p->hd_sec_sz = 1<<head->hd_sec_sz_s;
  131. p->hd_sec_sz_s = head->hd_sec_sz_s;
  132. p->n_hd_sec = wbfs_ntohl(head->n_hd_sec);
  133. p->n_wii_sec = (p->n_hd_sec/p->wii_sec_sz)*(p->hd_sec_sz);
  134. p->wbfs_sec_sz_s = head->wbfs_sec_sz_s;
  135. p->wbfs_sec_sz = 1<<p->wbfs_sec_sz_s;
  136. p->n_wbfs_sec = p->n_wii_sec >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
  137. p->n_wbfs_sec_per_disc = p->n_wii_sec_per_disc >> (p->wbfs_sec_sz_s - p->wii_sec_sz_s);
  138. p->disc_info_sz = ALIGN_LBA(sizeof(wbfs_disc_info_t) + p->n_wbfs_sec_per_disc*2);
  139. //printf("hd_sector_size %X wii_sector size %X wbfs sector_size %X\n",p->hd_sec_sz,p->wii_sec_sz,p->wbfs_sec_sz);
  140. p->read_hdsector = read_hdsector;
  141. p->write_hdsector = write_hdsector;
  142. #ifdef WIN32
  143. p->close_hd = close_hd;
  144. #endif
  145. p->callback_data = callback_data;
  146. p->freeblks_lba = (p->wbfs_sec_sz - p->n_wbfs_sec/8)>>p->hd_sec_sz_s;
  147. if(!reset)
  148. p->freeblks = 0; // will alloc and read only if needed
  149. else
  150. {
  151. // init with all free blocks
  152. p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8));
  153. wbfs_memset(p->freeblks,0xff,p->n_wbfs_sec/8);
  154. }
  155. p->max_disc = (p->freeblks_lba-1)/(p->disc_info_sz>>p->hd_sec_sz_s);
  156. if(p->max_disc > p->hd_sec_sz - sizeof(wbfs_head_t))
  157. p->max_disc = p->hd_sec_sz - sizeof(wbfs_head_t);
  158. p->tmp_buffer = wbfs_ioalloc(p->hd_sec_sz);
  159. p->n_disc_open = 0;
  160. wbfs_sync(p);
  161. return p;
  162. error:
  163. wbfs_free(p);
  164. wbfs_iofree(head);
  165. return 0;
  166. }
  167. void wbfs_sync(wbfs_t*p)
  168. {
  169. // copy back descriptors
  170. if(p->write_hdsector){
  171. p->write_hdsector(p->callback_data,p->part_lba+0,1, p->head);
  172. if(p->freeblks) {
  173. p->write_hdsector(p->callback_data,p->part_lba+p->freeblks_lba,ALIGN_LBA(p->n_wbfs_sec/8)>>p->hd_sec_sz_s, p->freeblks);
  174. }
  175. }
  176. }
  177. void wbfs_close(wbfs_t*p)
  178. {
  179. wbfs_sync(p);
  180. if(p->n_disc_open)
  181. WBFS_GOTO_ERROR("trying to close wbfs while discs still open");
  182. wbfs_iofree(p->head);
  183. wbfs_iofree(p->tmp_buffer);
  184. if(p->freeblks)
  185. wbfs_iofree(p->freeblks);
  186. #ifdef WIN32
  187. p->close_hd(p->callback_data);
  188. #endif
  189. wbfs_free(p);
  190. error:
  191. return;
  192. }
  193. wbfs_disc_t *wbfs_open_disc(wbfs_t* p, u8 *discid)
  194. {
  195. u32 i;
  196. int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  197. wbfs_disc_t *d = 0;
  198. for(i=0;i<p->max_disc;i++)
  199. {
  200. if (p->head->disc_table[i]){
  201. p->read_hdsector(p->callback_data,
  202. p->part_lba+1+i*disc_info_sz_lba,1,p->tmp_buffer);
  203. #ifdef WIN32
  204. if(_strnicmp(discid,p->tmp_buffer,6)==0){
  205. #else
  206. if(wbfs_memcmp(discid,p->tmp_buffer,6)==0){
  207. #endif
  208. d = wbfs_malloc(sizeof(*d));
  209. if(!d)
  210. WBFS_GOTO_ERROR("allocating memory");
  211. d->p = p;
  212. d->i = i;
  213. d->header = wbfs_ioalloc(p->disc_info_sz);
  214. if(!d->header)
  215. WBFS_GOTO_ERROR("allocating memory");
  216. p->read_hdsector(p->callback_data,
  217. p->part_lba+1+i*disc_info_sz_lba,
  218. disc_info_sz_lba,d->header);
  219. p->n_disc_open ++;
  220. // for(i=0;i<p->n_wbfs_sec_per_disc;i++)
  221. // printf("%d,",wbfs_ntohs(d->header->wlba_table[i]));
  222. return d;
  223. }
  224. }
  225. }
  226. #ifdef WIN32
  227. //_set_errno(ENOENT);
  228. #endif
  229. return 0;
  230. error:
  231. if (d) {
  232. wbfs_iofree(d);
  233. }
  234. #ifdef WIN32
  235. //_set_errno(ENOENT);
  236. #endif
  237. return 0;
  238. }
  239. void wbfs_close_disc(wbfs_disc_t*d)
  240. {
  241. d->p->n_disc_open --;
  242. wbfs_iofree(d->header);
  243. wbfs_free(d);
  244. }
  245. // offset is pointing 32bit words to address the whole dvd, although len is in bytes
  246. int wbfs_disc_read(wbfs_disc_t *d, u32 offset, u8 *data, u32 len)
  247. {
  248. wbfs_t *p = d->p;
  249. u16 wlba = offset>>(p->wbfs_sec_sz_s-2);
  250. u32 iwlba_shift = p->wbfs_sec_sz_s - p->hd_sec_sz_s;
  251. u32 lba_mask = (p->wbfs_sec_sz-1)>>(p->hd_sec_sz_s);
  252. u32 lba = (offset>>(p->hd_sec_sz_s-2))&lba_mask;
  253. u32 off = offset&((p->hd_sec_sz>>2)-1);
  254. u16 iwlba = wbfs_ntohs(d->header->wlba_table[wlba]);
  255. u32 len_copied;
  256. int err = 0;
  257. u8 *ptr = data;
  258. if(unlikely(iwlba==0))
  259. return 1;
  260. if(unlikely(off)){
  261. off*=4;
  262. err = p->read_hdsector(p->callback_data,
  263. p->part_lba + (iwlba<<iwlba_shift) + lba, 1, p->tmp_buffer);
  264. if(err)
  265. return err;
  266. len_copied = p->hd_sec_sz - off;
  267. if(likely(len < len_copied))
  268. len_copied = len;
  269. wbfs_memcpy(ptr, p->tmp_buffer + off, len_copied);
  270. len -= len_copied;
  271. ptr += len_copied;
  272. lba++;
  273. if(unlikely(lba>lba_mask && len)){
  274. lba=0;
  275. iwlba = wbfs_ntohs(d->header->wlba_table[++wlba]);
  276. if(unlikely(iwlba==0))
  277. return 1;
  278. }
  279. }
  280. while(likely(len>=p->hd_sec_sz))
  281. {
  282. u32 nlb = len>>(p->hd_sec_sz_s);
  283. if(unlikely(lba + nlb > p->wbfs_sec_sz)) // dont cross wbfs sectors..
  284. nlb = p->wbfs_sec_sz-lba;
  285. err = p->read_hdsector(p->callback_data,
  286. p->part_lba + (iwlba<<iwlba_shift) + lba, nlb, ptr);
  287. if(err)
  288. return err;
  289. len -= nlb<<p->hd_sec_sz_s;
  290. ptr += nlb<<p->hd_sec_sz_s;
  291. lba += nlb;
  292. if(unlikely(lba>lba_mask && len)){
  293. lba = 0;
  294. iwlba =wbfs_ntohs(d->header->wlba_table[++wlba]);
  295. if(unlikely(iwlba==0))
  296. return 1;
  297. }
  298. }
  299. if(unlikely(len)){
  300. err = p->read_hdsector(p->callback_data,
  301. p->part_lba + (iwlba<<iwlba_shift) + lba, 1, p->tmp_buffer);
  302. if(err)
  303. return err;
  304. wbfs_memcpy(ptr, p->tmp_buffer, len);
  305. }
  306. return 0;
  307. }
  308. // disc listing
  309. u32 wbfs_count_discs(wbfs_t*p)
  310. {
  311. u32 i,count=0;
  312. for(i=0;i<p->max_disc;i++)
  313. if (p->head->disc_table[i])
  314. count++;
  315. return count;
  316. }
  317. static u32 wbfs_sector_used(wbfs_t *p,wbfs_disc_info_t *di)
  318. {
  319. u32 tot_blk=0,j;
  320. for(j=0;j<p->n_wbfs_sec_per_disc;j++)
  321. if(wbfs_ntohs(di->wlba_table[j]))
  322. tot_blk++;
  323. return tot_blk;
  324. }
  325. u32 wbfs_get_disc_info(wbfs_t*p, u32 index,u8 *header,int header_size,u32 *size)//size in 32 bit
  326. {
  327. u32 i,count=0;
  328. int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  329. for(i=0;i<p->max_disc;i++)
  330. if (p->head->disc_table[i]){
  331. if(count++==index)
  332. {
  333. u32 magic;
  334. p->read_hdsector(p->callback_data,
  335. p->part_lba+1+i*disc_info_sz_lba,1,p->tmp_buffer);
  336. if(header_size > (int)p->hd_sec_sz)
  337. header_size = p->hd_sec_sz;
  338. magic = wbfs_ntohl(*(u32*)(p->tmp_buffer+24));
  339. if(magic!=0x5D1C9EA3){
  340. p->head->disc_table[i]=0;
  341. return 1;
  342. }
  343. memcpy(header,p->tmp_buffer,header_size);
  344. if(size)
  345. {
  346. u32 sec_used;
  347. u8 *header = wbfs_ioalloc(p->disc_info_sz);
  348. p->read_hdsector(p->callback_data,
  349. p->part_lba+1+i*disc_info_sz_lba,disc_info_sz_lba,header);
  350. sec_used = wbfs_sector_used(p,(wbfs_disc_info_t *)header);
  351. wbfs_iofree(header);
  352. *size = sec_used<<(p->wbfs_sec_sz_s-2);
  353. }
  354. return 0;
  355. }
  356. }
  357. return 1;
  358. }
  359. static void load_freeblocks(wbfs_t*p)
  360. {
  361. if(p->freeblks)
  362. return;
  363. // XXX should handle malloc error..
  364. p->freeblks = wbfs_ioalloc(ALIGN_LBA(p->n_wbfs_sec/8));
  365. p->read_hdsector(p->callback_data,p->part_lba+p->freeblks_lba,ALIGN_LBA(p->n_wbfs_sec/8)>>p->hd_sec_sz_s, p->freeblks);
  366. }
  367. u32 wbfs_count_usedblocks(wbfs_t*p)
  368. {
  369. u32 i,j,count=0;
  370. load_freeblocks(p);
  371. for(i=0;i<p->n_wbfs_sec/(8*4);i++)
  372. {
  373. u32 v = wbfs_ntohl(p->freeblks[i]);
  374. if(v == ~0U)
  375. count+=32;
  376. else if(v!=0)
  377. for(j=0;j<32;j++)
  378. if (v & (1<<j))
  379. count++;
  380. }
  381. return count;
  382. }
  383. // write access
  384. static int block_used(u8 *used,u32 i,u32 wblk_sz)
  385. {
  386. u32 k;
  387. i*=wblk_sz;
  388. for(k=0;k<wblk_sz;k++)
  389. if(i+k<143432*2 && used[i+k])
  390. return 1;
  391. return 0;
  392. }
  393. static u32 alloc_block(wbfs_t*p)
  394. {
  395. u32 i,j;
  396. for(i=0;i<p->n_wbfs_sec/(8*4);i++)
  397. {
  398. u32 v = wbfs_ntohl(p->freeblks[i]);
  399. if(v != 0)
  400. {
  401. for(j=0;j<32;j++)
  402. if (v & (1<<j))
  403. {
  404. p->freeblks[i] = wbfs_htonl(v & ~(1<<j));
  405. return (i*32)+j+1;
  406. }
  407. }
  408. }
  409. return ~0;
  410. }
  411. static void free_block(wbfs_t *p,int bl)
  412. {
  413. int i = (bl-1)/(32);
  414. int j = (bl-1)&31;
  415. u32 v = wbfs_ntohl(p->freeblks[i]);
  416. p->freeblks[i] = wbfs_htonl(v | 1<<j);
  417. }
  418. u32 wbfs_add_disc
  419. (
  420. wbfs_t *p,
  421. read_wiidisc_callback_t read_src_wii_disc,
  422. void *callback_data,
  423. progress_callback_t spinner,
  424. partition_selector_t sel,
  425. int copy_1_1
  426. #ifdef WIN32
  427. , char *new_name
  428. #endif
  429. )
  430. {
  431. int i, discn;
  432. u32 tot, cur;
  433. u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s-p->wii_sec_sz_s);
  434. wiidisc_t *d = 0;
  435. u8 *used = 0;
  436. wbfs_disc_info_t *info = 0;
  437. u8* copy_buffer = 0;
  438. u8 *b;
  439. int disc_info_sz_lba;
  440. used = wbfs_malloc(p->n_wii_sec_per_disc);
  441. if (!used)
  442. {
  443. WBFS_GOTO_ERROR("unable to alloc memory");
  444. }
  445. if (!copy_1_1)
  446. {
  447. d = wd_open_disc(read_src_wii_disc, callback_data);
  448. if(!d)
  449. {
  450. WBFS_GOTO_ERROR("unable to open wii disc");
  451. }
  452. wd_build_disc_usage(d, sel, used);
  453. wd_close_disc(d);
  454. d = 0;
  455. }
  456. for (i = 0; i < p->max_disc; i++) // find a free slot.
  457. {
  458. if (p->head->disc_table[i] == 0)
  459. {
  460. break;
  461. }
  462. }
  463. if (i == p->max_disc)
  464. {
  465. WBFS_GOTO_ERROR("no space left on device (table full)");
  466. }
  467. p->head->disc_table[i] = 1;
  468. discn = i;
  469. load_freeblocks(p);
  470. // build disc info
  471. info = wbfs_ioalloc(p->disc_info_sz);
  472. b = (u8 *)info;
  473. read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
  474. #ifdef WIN32
  475. if (new_name)
  476. {
  477. wbfs_memset(b+0x20, 0, 0x40);
  478. if(strlen(new_name)>=0x40) new_name[0x39]=0;
  479. strcpy(b+0x20, new_name);
  480. }
  481. #endif
  482. fprintf(stderr, "adding %c%c%c%c%c%c %s...\n",b[0], b[1], b[2], b[3], b[4], b[5], b + 0x20);
  483. copy_buffer = wbfs_ioalloc(p->wbfs_sec_sz);
  484. if (!copy_buffer)
  485. {
  486. WBFS_GOTO_ERROR("alloc memory");
  487. }
  488. tot = 0;
  489. cur = 0;
  490. if (spinner)
  491. {
  492. // count total number to write for spinner
  493. for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
  494. {
  495. if (copy_1_1 || block_used(used, i, wii_sec_per_wbfs_sect))
  496. {
  497. tot++;
  498. spinner(0, tot);
  499. }
  500. }
  501. }
  502. for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
  503. {
  504. u16 bl = 0;
  505. if (copy_1_1 || block_used(used, i, wii_sec_per_wbfs_sect))
  506. {
  507. bl = alloc_block(p);
  508. if (bl == 0xffff)
  509. {
  510. WBFS_GOTO_ERROR("no space left on device (disc full)");
  511. }
  512. if(read_src_wii_disc(callback_data, i * (p->wbfs_sec_sz >> 2), p->wbfs_sec_sz, copy_buffer))
  513. WBFS_GOTO_ERROR("error reading disc 3");
  514. // fix the partition table.
  515. if (i == (0x40000 >> p->wbfs_sec_sz_s))
  516. {
  517. wd_fix_partition_table(d, sel, copy_buffer + (0x40000 & (p->wbfs_sec_sz - 1)));
  518. }
  519. p->write_hdsector(p->callback_data, p->part_lba + bl * (p->wbfs_sec_sz / p->hd_sec_sz),
  520. p->wbfs_sec_sz / p->hd_sec_sz, copy_buffer);
  521. if (spinner)
  522. {
  523. cur++;
  524. spinner(cur, tot);
  525. }
  526. }
  527. info->wlba_table[i] = wbfs_htons(bl);
  528. }
  529. // write disc info
  530. disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  531. p->write_hdsector(p->callback_data, p->part_lba + 1 + discn * disc_info_sz_lba,disc_info_sz_lba, info);
  532. wbfs_sync(p);
  533. if(d)
  534. wd_close_disc(d);
  535. if(used)
  536. wbfs_free(used);
  537. if(info)
  538. wbfs_iofree(info);
  539. if(copy_buffer)
  540. wbfs_iofree(copy_buffer);
  541. // init with all free blocks
  542. return 0;
  543. error:
  544. if(d)
  545. wd_close_disc(d);
  546. if(used)
  547. wbfs_free(used);
  548. if(info)
  549. wbfs_iofree(info);
  550. if(copy_buffer)
  551. wbfs_iofree(copy_buffer);
  552. // init with all free blocks
  553. return 1;
  554. }
  555. u32 wbfs_ren_disc(wbfs_t*p, u8* discid, u8* newname)
  556. {
  557. wbfs_disc_t *d = wbfs_open_disc(p, discid);
  558. int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  559. if(!d)
  560. return 1;
  561. memset(d->header->disc_header_copy+0x20, 0, 0x40);
  562. strncpy(d->header->disc_header_copy+0x20, (char*)newname, 0x39);
  563. d->header->disc_header_copy[0x20+0x39] = '\0'; //force last char to 0
  564. p->write_hdsector(p->callback_data,
  565. p->part_lba+1+d->i*disc_info_sz_lba,
  566. disc_info_sz_lba,
  567. d->header);
  568. wbfs_close_disc(d);
  569. wbfs_sync(p);
  570. return 0;
  571. }
  572. u32 wbfs_nid_disc(wbfs_t*p, u8* discid, u8* newid)
  573. {
  574. wbfs_disc_t *d = wbfs_open_disc(p, discid);
  575. int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  576. if(!d)
  577. return 1;
  578. if(strlen((const char *)newid) > 0x6)
  579. return 1;
  580. strcpy((char *)(d->header->disc_header_copy+0x0), (const char *)newid);
  581. p->write_hdsector(p->callback_data,
  582. p->part_lba+1+d->i*disc_info_sz_lba,
  583. disc_info_sz_lba,
  584. d->header);
  585. wbfs_close_disc(d);
  586. wbfs_sync(p);
  587. return 0;
  588. }
  589. u32 wbfs_estimate_disc
  590. (
  591. wbfs_t *p, read_wiidisc_callback_t read_src_wii_disc,
  592. void *callback_data,
  593. partition_selector_t sel, u8* header
  594. )
  595. {
  596. u8 *b;
  597. int i;
  598. u32 tot;
  599. u32 wii_sec_per_wbfs_sect = 1 << (p->wbfs_sec_sz_s-p->wii_sec_sz_s);
  600. wiidisc_t *d = 0;
  601. u8 *used = 0;
  602. wbfs_disc_info_t *info = 0;
  603. tot = 0;
  604. used = wbfs_malloc(p->n_wii_sec_per_disc);
  605. if (!used)
  606. {
  607. WBFS_GOTO_ERROR("unable to alloc memory");
  608. }
  609. d = wd_open_disc(read_src_wii_disc, callback_data);
  610. if (!d)
  611. {
  612. WBFS_GOTO_ERROR("unable to open wii disc");
  613. }
  614. int result = wd_build_disc_usage(d,sel,used);
  615. wd_close_disc(d);
  616. d = 0;
  617. info = wbfs_ioalloc(p->disc_info_sz);
  618. b = (u8 *)info;
  619. read_src_wii_disc(callback_data, 0, 0x100, info->disc_header_copy);
  620. for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
  621. {
  622. if (block_used(used, i, wii_sec_per_wbfs_sect))
  623. {
  624. tot++;
  625. }
  626. }
  627. if(result)
  628. {
  629. memcpy(header, b,0x100);
  630. }
  631. error:
  632. if (d)
  633. wd_close_disc(d);
  634. if (used)
  635. wbfs_free(used);
  636. if (info)
  637. wbfs_iofree(info);
  638. return !result ? 0 : tot * ((p->wbfs_sec_sz / p->hd_sec_sz) * 512);
  639. }
  640. u32 wbfs_rm_disc(wbfs_t*p, u8* discid)
  641. {
  642. wbfs_disc_t *d = wbfs_open_disc(p,discid);
  643. int i;
  644. int discn = 0;
  645. int disc_info_sz_lba = p->disc_info_sz>>p->hd_sec_sz_s;
  646. if(!d)
  647. return 1;
  648. load_freeblocks(p);
  649. discn = d->i;
  650. for( i=0; i< p->n_wbfs_sec_per_disc; i++)
  651. {
  652. u32 iwlba = wbfs_ntohs(d->header->wlba_table[i]);
  653. if (iwlba)
  654. free_block(p,iwlba);
  655. }
  656. memset(d->header,0,p->disc_info_sz);
  657. p->write_hdsector(p->callback_data,p->part_lba+1+discn*disc_info_sz_lba,disc_info_sz_lba,d->header);
  658. p->head->disc_table[discn] = 0;
  659. wbfs_close_disc(d);
  660. wbfs_sync(p);
  661. return 0;
  662. }
  663. /* trim the file-system to its minimum size
  664. */
  665. u32 wbfs_trim(wbfs_t*p)
  666. {
  667. u32 maxbl;
  668. load_freeblocks(p);
  669. maxbl = alloc_block(p);
  670. p->n_hd_sec = maxbl<<(p->wbfs_sec_sz_s-p->hd_sec_sz_s);
  671. p->head->n_hd_sec = wbfs_htonl(p->n_hd_sec);
  672. // make all block full
  673. memset(p->freeblks,0,p->n_wbfs_sec/8);
  674. wbfs_sync(p);
  675. // os layer will truncate the file.
  676. return maxbl;
  677. }
  678. // data extraction
  679. u32 wbfs_extract_disc(wbfs_disc_t*d, rw_sector_callback_t write_dst_wii_sector,void *callback_data,progress_callback_t spinner)
  680. {
  681. wbfs_t *p = d->p;
  682. u8* copy_buffer = 0;
  683. int tot = 0, cur = 0;
  684. int i;
  685. int filling_info = 0;
  686. int src_wbs_nlb=p->wbfs_sec_sz/p->hd_sec_sz;
  687. int dst_wbs_nlb=p->wbfs_sec_sz/p->wii_sec_sz;
  688. copy_buffer = wbfs_ioalloc(p->wbfs_sec_sz);
  689. if (!copy_buffer)
  690. WBFS_GOTO_ERROR("alloc memory");
  691. if (spinner)
  692. {
  693. // count total number to write for spinner
  694. for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
  695. {
  696. u32 iwlba = wbfs_ntohs(d->header->wlba_table[i]);
  697. if (iwlba)
  698. {
  699. tot++;
  700. spinner(0, tot);
  701. }
  702. }
  703. }
  704. for (i = 0; i < p->n_wbfs_sec_per_disc; i++)
  705. {
  706. u32 iwlba = wbfs_ntohs(d->header->wlba_table[i]);
  707. if (iwlba)
  708. {
  709. cur++;
  710. if (spinner)
  711. spinner(cur,tot);
  712. if(p->read_hdsector(p->callback_data, p->part_lba + iwlba*src_wbs_nlb, src_wbs_nlb, copy_buffer))
  713. WBFS_GOTO_ERROR("reading disc");
  714. if(write_dst_wii_sector(callback_data, i*dst_wbs_nlb, dst_wbs_nlb, copy_buffer))
  715. WBFS_GOTO_ERROR("writing disc");
  716. }
  717. else
  718. {
  719. switch (filling_info) {
  720. case 0:
  721. if (cur == tot)
  722. filling_info = 1;
  723. break;
  724. case 1:
  725. fprintf(stderr, "Filling empty space in extracted image. Please wait...\n");
  726. filling_info = 2;
  727. break;
  728. case 2:
  729. default:
  730. break;
  731. }
  732. }
  733. }
  734. wbfs_iofree(copy_buffer);
  735. return 0;
  736. error:
  737. return 1;
  738. }
  739. u32 wbfs_extract_file(wbfs_disc_t* d, char *path);