1 
2 /***************************************************************************
3  *                    __            __ _ ___________                       *
4  *                    \ \          / /| |____   ____|                      *
5  *                     \ \        / / | |    | |                           *
6  *                      \ \  /\  / /  | |    | |                           *
7  *                       \ \/  \/ /   | |    | |                           *
8  *                        \  /\  /    | |    | |                           *
9  *                         \/  \/     |_|    |_|                           *
10  *                                                                         *
11  *                           Wiimms ISO Tools                              *
12  *                         http://wit.wiimm.de/                            *
13  *                                                                         *
14  ***************************************************************************
15  *                                                                         *
16  *   This file is part of the WIT project.                                 *
17  *   Visit http://wit.wiimm.de/ for project details and sources.           *
18  *                                                                         *
19  *   Copyright (c) 2009 Kwiirk                                             *
20  *   Copyright (c) 2009-2013 by Dirk Clemens <wiimm@wiimm.de>              *
21  *                                                                         *
22  ***************************************************************************
23  *                                                                         *
24  *   This program is free software; you can redistribute it and/or modify  *
25  *   it under the terms of the GNU General Public License as published by  *
26  *   the Free Software Foundation; either version 2 of the License, or     *
27  *   (at your option) any later version.                                   *
28  *                                                                         *
29  *   This program is distributed in the hope that it will be useful,       *
30  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
31  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
32  *   GNU General Public License for more details.                          *
33  *                                                                         *
34  *   See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt       *
35  *                                                                         *
36  ***************************************************************************/
37 
38 #ifndef LIBWBFS_H
39 #define LIBWBFS_H
40 
41 #include "file-formats.h"
42 #include "wiidisc.h"
43 
44 #ifdef __cplusplus
45 extern "C"
46 {
47 #endif /* __cplusplus */
48 
49 ///////////////////////////////////////////////////////////////////////////////
50 
51 #define WBFS_MAGIC ( 'W'<<24 | 'B'<<16 | 'F'<<8 | 'S' )
52 #define WBFS_VERSION 1
53 #define WBFS_NO_BLOCK (~(u32)0)
54 
55 ///////////////////////////////////////////////////////////////////////////////
56 
57 //  WBFS first wbfs_sector structure:
58 //
59 //  -----------
60 // | wbfs_head |  (hd_sec_sz)
61 //  -----------
62 // |	       |
63 // | disc_info |
64 // |	       |
65 //  -----------
66 // |	       |
67 // | disc_info |
68 // |	       |
69 //  -----------
70 // |	       |
71 // | ...       |
72 // |	       |
73 //  -----------
74 // |	       |
75 // | disc_info |
76 // |	       |
77 //  -----------
78 // |	       |
79 // |freeblk_tbl|
80 // |	       |
81 //  -----------
82 //
83 
84 //-----------------------------------------------------------------------------
85 
86 // callback definition. Return 1 on fatal error
87 // (callback is supposed to make retries until no hopes..)
88 
89 typedef int (*rw_sector_callback_t)(void*fp,u32 lba,u32 count,void*iobuf);
90 typedef void (*progress_callback_t) (u64 done, u64 total, void * callback_data );
91 
92 //-----------------------------------------------------------------------------
93 
94 typedef enum wbfs_slot_mode_t
95 {
96     //--- the base info
97 
98     WBFS_SLOT_FREE	= 0x00,  // dics slot is unused
99     WBFS_SLOT_VALID	= 0x01,  // dics slot is used and disc seems valid
100     WBFS_SLOT_INVALID	= 0x02,  // dics slot is used but disc is invalid
101 
102     //--- some additionally flags
103 
104     WBFS_SLOT_F_SHARED	= 0x04,  // flag: disc is/was sharing a block with other disc
105     WBFS_SLOT_F_FREED	= 0x08,  // flag: disc is/was using a 'marked free' block
106 
107     //--- more values
108 
109     WBFS_SLOT__MASK	= 0x0f,  // mask of all values above
110     WBFS_SLOT__USER	= 0x10,  // first free bit for extern usage
111 
112 } wbfs_slot_mode_t;
113 
114 extern char wbfs_slot_mode_info[WBFS_SLOT__MASK+1];
115 
116 //-----------------------------------------------------------------------------
117 
118 typedef enum wbfs_balloc_mode_t // block allocation mode
119 {
120     WBFS_BA_AUTO,	// let add disc the choice:
121 			// for small WBFS partitons (<20G) use WBFS_BA_FIRST
122 			// and all for other WBFS partitons use WBFS_BA_NO_FRAG
123 
124     WBFS_BA_FIRST,	// don't find large blocks and use always the first free block
125     WBFS_BA_AVOID_FRAG,	// try to avoid fragments
126 
127     WBFS_BA_DEFAULT	= WBFS_BA_AUTO
128 
129 } wbfs_balloc_mode_t;
130 
131 //-----------------------------------------------------------------------------
132 
133 typedef struct wbfs_t
134 {
135     wbfs_head_t	* head;
136 
137     /* hdsectors, the size of the sector provided by the hosting hard drive */
138     u32		hd_sec_sz;
139     u8		hd_sec_sz_s;		// the power of two of the last number
140     u32		n_hd_sec;		// the number of hd sector in the wbfs partition
141 
142     /* standard wii sector (0x8000 bytes) */
143     u32		wii_sec_sz;		// always WII_SECTOR_SIZE
144     u8		wii_sec_sz_s;		// always 15
145     u32		n_wii_sec;
146     u32		n_wii_sec_per_disc;	// always WII_MAX_SECTORS
147 
148     /* The size of a wbfs sector */
149     u32		wbfs_sec_sz;
150     u32		wbfs_sec_sz_s;
151     u16		n_wbfs_sec;		// this must fit in 16 bit!
152     u16		n_wbfs_sec_per_disc;	// size of the lookup table
153 
154     u32		part_lba;		// the lba of the wbfs header
155 
156     /* virtual methods to read write the partition */
157     rw_sector_callback_t read_hdsector;
158     rw_sector_callback_t write_hdsector;
159     void	* callback_data;
160 
161     u16		max_disc;		// maximal number of possible discs
162     u32		freeblks_lba;		// the hd sector of the free blocks table
163     u32		freeblks_lba_count;	// number of hd sector used by free blocks table
164     u32		freeblks_size4;		// size in u32 of free blocks table
165     u32		freeblks_mask;		// mask for last used u32 of freeblks
166     u32		* freeblks;		// if not NULL: copy of free blocks table
167 
168     u8		* block0;		// NULL or copy of wbfs block #0
169     u8		* used_block;		// For each WBFS block 1 byte, N='n_wbfs_sec'
170 					//    0: unused			==> OK
171 					//    1: normal (=single) usage	==> OK
172 					//   >1: shared by #N discs	==> BAD!
173 					//  127: shared by >=127 discs	==> BAD!
174 					// >128: reserved for internal usage
175 					//  255: header block #0
176     bool	used_block_dirty;	// true: 'used_block' must be written to disc
177     wbfs_slot_mode_t	new_slot_err;	// new detected errors
178     wbfs_slot_mode_t	all_slot_err;	// all detected errros
179     wbfs_balloc_mode_t	balloc_mode;	// block allocation mode
180 
181     u16		disc_info_sz;
182 
183     u8		* tmp_buffer;		// pre-allocated buffer for unaligned read
184     id6_t	*id_list;		// list with all disc ids
185 
186     bool	is_dirty;		// if >0: call wbfs_sync() on close
187     u32		n_disc_open;		// number of open discs
188 
189 } wbfs_t;
190 
191 //-----------------------------------------------------------------------------
192 
193 typedef struct wbfs_disc_t
194 {
195     wbfs_t		* p;
196     wbfs_disc_info_t	* header;	// pointer to wii header
197     int			slot;		// disc slot, range= 0 .. wbfs_t::max_disc-1
198     wd_disc_type_t	disc_type;	// disc type
199     wd_disc_attrib_t	disc_attrib;	// disc attrib
200     uint		disc_blocks;	// >0: number of blocks
201     uint		n_fragments;	// >0: number of fragments
202     bool		is_used;	// disc is marked as 'used'?
203     bool		is_valid;	// disc has valid id and magic
204     bool		is_deleted;	// disc has valid id and deleted_magic
205     bool		is_iinfo_valid;	// disc has a valid wbfs_inode_info_t
206     bool		is_creating;	// disc is in creation process
207     bool		is_dirty;	// if >0: call wbfs_sync_disc_header() on close
208 
209 } wbfs_disc_t;
210 
211 //-----------------------------------------------------------------------------
212 
213 be64_t	wbfs_setup_inode_info
214 	( wbfs_t * p, wbfs_inode_info_t * ii, bool is_valid, int is_changed );
215 
216 int wbfs_is_inode_info_valid
217 (
218     // if valid   -> return WBFS_INODE_INFO_VERSION
219     // if invalid -> return 0
220 
221     const wbfs_t		* p,	// NULL or WBFS
222     const wbfs_inode_info_t	* ii	// NULL or inode pointer
223 );
224 
225 //-----------------------------------------------------------------------------
226 
227 typedef struct wbfs_param_t // function parameters
228 {
229   //----- parameters for wbfs_open_partition_param()
230 
231 	// call back data
232 	rw_sector_callback_t	read_hdsector;		// read sector function
233 	rw_sector_callback_t	write_hdsector;		// write sector function
234 
235 	// needed parameters
236 	u32			hd_sector_size;		// HD sector size (0=>512)
237 	u32			part_lba;		// partition LBA delta
238 	int			old_wii_sector_calc;	// >0 => use old & buggy calculation
239 	int			force_mode;		// >0 => no plausibility tests
240 	int			reset;			// >0 => format disc
241 
242 	// only used if formatting disc (if reset>0)
243 	u32			num_hd_sector;		// num of HD sectors
244 	int			clear_inodes;		// >0 => clear inodes
245 	int			setup_iinfo;		// >0 => clear inodes & use iinfo
246 	int			wbfs_sector_size;	// >0 => force wbfs_sec_sz_s
247 
248 
249   //----- parameters for wbfs_open_partition_param()
250 
251 	// call back data
252 	wd_read_func_t		read_src_wii_disc;	// read wit sector [obsolete?]
253 	progress_callback_t	spinner;		// progress callback
254 	wbfs_balloc_mode_t	balloc_mode;		// block allocation mode
255 
256 
257   //----- parameters for wbfs_add_disc_param()
258 
259 	u64			iso_size;		// size of iso image in bytes
260 	wd_disc_t		*wd_disc;		// NULL or the source disc
261 	const wd_select_t	*psel;			// partition selector
262 	id6_t			wbfs_id6;		// not NULL: use this ID for inode
263 
264 
265   //----- multi use parameters
266 
267 	// call back data
268 	void			*callback_data;		// used defined data
269 
270 	// inode info
271 	wbfs_inode_info_t	iinfo;			// additional infos
272 
273 
274   //----- infos (output of wbfs framework)
275 
276 	int			slot;			// >=0: slot of last added disc
277 	wbfs_disc_t		*open_disc;		// NULL or open disc
278 
279 } wbfs_param_t;
280 
281 //-----------------------------------------------------------------------------
282 
283 #ifndef WIT // not used in WiT
284 
285 wbfs_t * wbfs_open_partition
286 (
287     rw_sector_callback_t	read_hdsector,
288     rw_sector_callback_t	write_hdsector,
289     void			* callback_data,
290     int				hd_sector_size,
291     int				num_hd_sector,
292     u32				part_lba,
293     int				reset
294 );
295 
296 #endif
297 
298 wbfs_t * wbfs_open_partition_param ( wbfs_param_t * par );
299 
300 int wbfs_calc_size_shift
301 	( u32 hd_sec_sz_s, u32 num_hd_sector, int old_wii_sector_calc );
302 
303 u32 wbfs_calc_sect_size ( u64 total_size, u32 hd_sec_size );
304 
305 void wbfs_calc_geometry
306 (
307     wbfs_t		* p,		// pointer to wbfs_t, p->head must be NULL or valid
308     u32			n_hd_sec,	// total number of hd_sec in partition
309     u32			hd_sec_sz,	// size of a hd/partition sector
310     u32			wbfs_sec_sz	// size of a wbfs sector
311 );
312 
313 //-----------------------------------------------------------------------------
314 
315 void wbfs_close ( wbfs_t * p );
316 void wbfs_sync  ( wbfs_t * p );
317 
318 wbfs_disc_t * wbfs_open_disc_by_id6  ( wbfs_t * p, u8 * id6 );
319 wbfs_disc_t * wbfs_open_disc_by_slot ( wbfs_t * p, u32 slot, int force_open );
320 
321 wbfs_disc_t * wbfs_create_disc
322 (
323     wbfs_t	* p,		// valid WBFS descriptor
324     const void	* disc_header,	// NULL or disc header to copy
325     const void	* disc_id	// NULL or ID6: check non existence
326 				// disc_id overwrites the id of disc_header
327 );
328 
329 int wbfs_sync_disc_header ( wbfs_disc_t * d );
330 void wbfs_close_disc ( wbfs_disc_t * d );
331 
332 wbfs_inode_info_t * wbfs_get_inode_info ( wbfs_t *p, wbfs_disc_info_t *info, int clear_mode );
333 wbfs_inode_info_t * wbfs_get_disc_inode_info ( wbfs_disc_t * d, int clear_mode );
334 	// clear_mode == 0 : don't clear
335 	// clear_mode == 1 : clear if invalid
336 	// clear_mode == 2 : clear always
337 
338 uint wbfs_get_fragments
339 (
340     const u16		* wlba_tab,	// valid wlba table in network byte order
341     uint		tab_length,	// length of 'wlba_tab'
342     uint		* disc_blocks	// not NULL: store number of disc blocks
343 );
344 
345 uint wbfs_get_disc_fragments
346 (
347     wbfs_disc_t		*d,		// valid wbfs disc
348     uint		* disc_blocks	// not NULL: store number of disc blocks
349 );
350 
351 //-----------------------------------------------------------------------------
352 
353 int wbfs_rename_disc
354 (
355     wbfs_disc_t		* d,		// pointer to an open disc
356     const char		* new_id,	// if !NULL: take the first 6 chars as ID
357     const char		* new_title,	// if !NULL: take the first 0x39 chars as title
358     int			chg_wbfs_head,	// if !0: change ID/title of WBFS header
359     int			chg_iso_head	// if !0: change ID/title of ISO header
360 );
361 
362 //-----------------------------------------------------------------------------
363 
364 int wbfs_touch_disc
365 (
366     wbfs_disc_t		* d,		// pointer to an open disc
367     u64			itime,		// if != 0: new itime
368     u64			mtime,		// if != 0: new mtime
369     u64			ctime,		// if != 0: new ctime
370     u64			atime		// if != 0: new atime
371 );
372 
373 //-----------------------------------------------------------------------------
374 
375 void wbfs_print_block_usage
376 (
377     FILE		* f,		// valid output file
378     int			indent,		// indention of the output
379     const wbfs_t	* p,		// valid WBFS descriptor
380     bool		print_all	// false: ignore const lines
381 );
382 
383 //-----------------------------------------------------------------------------
384 
385 extern const char wbfs_usage_name_tab[256];
386 
387 void wbfs_print_usage_tab
388 (
389     FILE		* f,		// valid output file
390     int			indent,		// indention of the output
391     const u8		* used_block,	// valid pointer to usage table
392     u32			block_used_sz,	// size of 'used_block'
393     u32			sector_size,	// wbfs sector size
394     bool		print_all	// false: ignore const lines
395 );
396 
397 //-----------------------------------------------------------------------------
398 
399 typedef enum wbfs_check_t
400 {
401     WBFS_CHK_DONE = 0,			// finish message
402 
403     WBFS_CHK_UNUSED_BLOCK,		// block marked used, but is not used [block]
404     WBFS_CHK_MULTIUSED_BLOCK,		// block used multiple times [block,count]
405 
406     WBFS_CHK_INVALID_BLOCK,		// invalid block number [slot,id6,block]
407     WBFS_CHK_FREE_BLOCK_USED,		// block marked free but used [slot,id6,block]
408     WBFS_CHK_SHARED_BLOCK,		// usage of a shared block by [slot,id6,block,count]
409 
410 } wbfs_check_t;
411 
412 //-----------------------------------------------------------------------------
413 
414 typedef void (*wbfs_check_func)
415 (
416     wbfs_t		* p,		// valid WBFS descriptor
417     wbfs_check_t	check_mode,	// modus
418     int			slot,		// -1 or related slot index
419     ccp			id6,		// NULL or pointer to disc ID6
420     int			block,		// -1 or related block number
421     uint		count,		// block usage count
422     ccp			msg,		// clear text message
423     uint		msg_len,	// strlen(msg)
424     void		* param		// user defined paramater
425 );
426 
427 //-----------------------------------------------------------------------------
428 
429 int wbfs_calc_used_blocks
430 (
431     wbfs_t		* p,		// valid WBFS descriptor
432     bool		force_reload,	// true: definitely reload block #0
433     bool		store_block0,	// true: don't free block0
434     wbfs_check_func	func,		// call back function for errors
435     void		* param		// user defined parameter
436 );
437 
438 //-----------------------------------------------------------------------------
439 
440 u32 wbfs_find_free_blocks
441 (
442     // returns index of first free block or WBFS_NO_BLOCK if not enough blocks free
443 
444     wbfs_t	* p,		// valid WBFS descriptor
445     u32		n_needed	// number of needed blocks
446 );
447 
448 //-----------------------------------------------------------------------------
449 
450 /*! @return the number of discs inside the paritition */
451 u32 wbfs_count_discs(wbfs_t*p);
452 
453 u32 wbfs_alloc_block
454 (
455     wbfs_t		* p,		// valid WBFS descriptor
456     u32			start_block	// >0: start search at this block
457 );
458 
459 enumError wbfs_get_disc_info
460 (
461     wbfs_t		* p,		// valid wbfs descriptor
462     u32			index,		// disc index: 0 .. num_dics-1
463     u8			* header,	// header to store data
464     int			header_size,	// size of 'header'
465     u32			* slot_found,	// not NULL: store slot of found disc
466     wd_disc_type_t	* disc_type,	// not NULL: store disc type
467     wd_disc_attrib_t	* disc_attrib,	// not NULL: store disc attrib
468     u32			* size4,	// not NULL: store 'size>>2' of found disc
469     u32			* n_fragments	// number of wbfs fragments
470 );
471 
472 enumError wbfs_get_disc_info_by_slot
473 (
474     wbfs_t		* p,		// valid wbfs descriptor
475     u32			slot,		// disc index: 0 .. num_dics-1
476     u8			* header,	// not NULL: header to store data
477     int			header_size,	// size of 'header'
478     wd_disc_type_t	* disc_type,	// not NULL: store disc type
479     wd_disc_attrib_t	* disc_attrib,	// not NULL: store disc attrib
480     u32			* size4,	// not NULL: store 'size>>2' of found disc
481     u32			* n_fragments	// number of wbfs fragments
482 );
483 
484 /*! get the number of unuseds block of the partition.
485   to be multiplied by p->wbfs_sec_sz (use 64bit multiplication) to have the number in bytes
486 */
487 u32 wbfs_get_free_block_count ( wbfs_t * p );
488 
489 /******************* write access  ******************/
490 
491 id6_t * wbfs_load_id_list	( wbfs_t * p, int force_reload );
492 int  wbfs_find_slot		( wbfs_t * p, const u8 * disc_id );
493 
494 u32 * wbfs_free_freeblocks	( wbfs_t * p );
495 u32 * wbfs_load_freeblocks	( wbfs_t * p );
496 void wbfs_free_block		( wbfs_t * p, u32 bl );
497 void wbfs_use_block		( wbfs_t * p, u32 bl );
498 u32 wbfs_find_last_used_block	( wbfs_t * p );
499 
500 /*! add a wii dvd inside the partition
501   @param read_src_wii_disc: a callback to access the wii dvd. offsets are in 32bit, len in bytes!
502   @callback_data: private data passed to the callback
503   @spinner: a pointer to a function that is regulary called to update a progress bar.
504   @sel: selects which partitions to copy.
505   @copy_1_1: makes a 1:1 copy, whenever a game would not use the wii disc format, and some data is hidden outside the filesystem.
506  */
507 u32 wbfs_add_disc
508 (
509     wbfs_t		* p,
510     wd_read_func_t	read_src_wii_disc,
511     void		* callback_data,
512     progress_callback_t	spinner,
513     const wd_select_t	* psel,
514     int			copy_1_1
515 );
516 
517 u32 wbfs_add_disc_param ( wbfs_t * p, wbfs_param_t * par );
518 
519 u32 wbfs_add_phantom ( wbfs_t *p, ccp phantom_id, u32 wii_sectors );
520 
521 // remove a disc from partition
522 u32 wbfs_rm_disc
523 (
524     wbfs_t		* p,		// valid WBFS descriptor
525     u8			* discid,	// id6 to remove. If NULL: remove 'slot'
526     int			slot,		// slot index, only used if 'discid==NULL'
527     int			free_slot_only	// true: do not free blocks
528 );
529 
530 /*! trim the file-system to its minimum size
531   This allows to use wbfs as a wiidisc container
532  */
533 u32 wbfs_trim(wbfs_t*p);
534 
535 /* OS specific functions provided by libwbfs_<os>.c */
536 
537 wbfs_t *wbfs_try_open(char *disk, char *partition, int reset);
538 wbfs_t *wbfs_try_open_partition(char *fn, int reset);
539 
540 void *wbfs_open_file_for_read(char*filename);
541 void *wbfs_open_file_for_write(char*filename);
542 int wbfs_read_file(void*handle, int len, void *buf);
543 void wbfs_close_file(void *handle);
544 void wbfs_file_reserve_space(void*handle,long long size);
545 void wbfs_file_truncate(void *handle,long long size);
546 int wbfs_read_wii_file(void *_handle, u32 _offset, u32 count, void *buf);
547 int wbfs_write_wii_sector_file(void *_handle, u32 lba, u32 count, void *buf);
548 
549 ///////////////////////////////////////////////////////////////////////////////
550 
551 #ifdef __cplusplus
552 }
553 #endif /* __cplusplus */
554 
555 #endif // LIBWBFS_H
556