2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: super.c 911 2005-03-14 21:02:17Z oopo $
11 # PFS superblock manipulation routines
16 int checkZoneSize(u32 zone_size
)
18 if((zone_size
& (zone_size
- 1)) || (zone_size
< (2 * 1024)) || (zone_size
> (128 * 1024)))
20 printf("ps2fs: Error: Invalid zone size\n");
27 // Returns the number of sectors (512 byte units) which will be used
28 // for bitmaps, given the zone size and partition size
29 u32
getBitmapSectors(int zoneScale
, u32 partSize
)
31 int w
, zones
= partSize
/ (1 << zoneScale
);
34 zones
= zones
/ 8 + w
;
37 return zones
/ 512 + w
;
40 // Returns the number of blocks/zones which will be used for bitmaps
41 u32
getBitmapBocks(int scale
, u32 mainsize
)
43 u32 a
=getBitmapSectors(scale
, mainsize
);
44 return a
/ (1<<scale
) + ((a
% (1<<scale
))>0);
47 // Formats a partition (main or sub) by filling with fragment pattern and setting the bitmap accordingly
48 int formatSub(block_device
*blockDev
, int fd
, u32 sub
, u32 reserved
, u32 scale
, u32 fragment
)
52 u32 sector
, count
, size
, *b
;
55 size
= blockDev
->getSize(fd
, sub
);
57 count
= getBitmapSectors(scale
, size
);
60 reserved
+= getBitmapBocks(scale
, size
);
62 if((cache
= cacheAllocClean(&result
)))
64 // fill with fragment pattern
65 for (i
=127; i
>=0; i
--)
66 cache
->u
.bitmap
[i
]=fragment
;
68 // set as allocated the sectors up to reserved, for the first part of the bitmap
69 // this will mark the area the bitmaps themselves occupy as used
70 for (i
=0, b
=cache
->u
.bitmap
; i
<reserved
; i
++)
72 if (i
&& ((i
& 0x1F)==0))
74 *b
|= 1 << (i
& 0x1F);
77 dprintf("ps2fs: Format sub: sub = %ld, sector start = %ld, ", sub
, sector
);
79 // set the rest of the bitmap to the fragment
80 while (count
-- && ((result
=blockDev
->transfer(fd
, cache
->u
.bitmap
, sub
, sector
++, 1, 1))>=0))
81 for (i
=127; i
>=0; i
--)
82 cache
->u
.bitmap
[i
]=fragment
;
84 dprintf("sector end = %ld\n", sector
- 1);
91 // Formats a partition and all sub-partitions with PFS
92 int _format(block_device
*blockDev
, int fd
, int zonesize
, int fragment
)
95 pfs_cache_t
*clink
, *cache
;
98 u32 i
, mainsize
, subnumber
= blockDev
->getSubNumber(fd
);
100 mainsize
=blockDev
->getSize(fd
, 0);
101 if(checkZoneSize(zonesize
) == 0)
104 scale
= getScale(zonesize
, 512);
106 if((clink
=cacheAllocClean(&result
)))
108 sb
= clink
->u
.superblock
;
109 memset(sb
, 0, metaSize
);
110 sb
->magic
= PFS_SUPER_MAGIC
;
112 sb
->unknown1
= 0x201;
113 sb
->zone_size
= zonesize
;
114 sb
->num_subs
= subnumber
;
115 sb
->log
.number
= getBitmapBocks(scale
, mainsize
) + (0x2000 >> scale
) + 1;
116 sb
->log
.count
= 0x20000 / zonesize
? 0x20000 / zonesize
: 1;
118 dprintf("ps2fs: Format: log.number = %ld, log.count = %d\n", sb
->log
.number
<< scale
, sb
->log
.count
);
121 sb
->root
.number
= sb
->log
.number
+ sb
->log
.count
;
122 if((result
= journalResetThis(blockDev
, fd
, sb
->log
.number
<<scale
)) >= 0)
124 if((cache
= cacheAllocClean(&result2
)))
126 fillSelfAndParentDentries(cache
, &sb
->root
, &sb
->root
);
127 result2
= blockDev
->transfer(fd
, cache
->u
.dentry
, 0, (sb
->root
.number
+1) << scale
,
131 // setup root directory
132 inodeFill(cache
, &sb
->root
, 0x11FF, 0, 0);
133 cache
->u
.inode
->data
[1].subpart
= 0;
134 cache
->u
.inode
->data
[1].number
= sb
->root
.number
+ 1;
135 cache
->u
.inode
->data
[1].count
= 1;
136 cache
->u
.inode
->checksum
= inodeCheckSum(cache
->u
.inode
);
138 result2
=blockDev
->transfer(fd
, cache
->u
.inode
, 0, sb
->root
.number
<< scale
,
145 if((result
= result2
) >= 0)
147 for (i
=0; i
< subnumber
+1; i
++)
148 if((result
=formatSub(blockDev
, fd
, i
, i
? 1 : (0x2000 >> scale
) +
149 sb
->log
.count
*8, scale
, fragment
))<0)
152 if((result
== 0) && ((result
= blockDev
->transfer(fd
, sb
, 0, PFS_SUPER_BACKUP_SECTOR
, 1, 1))==0))
153 result
= blockDev
->transfer(fd
, sb
, 0, PFS_SUPER_SECTOR
, 1, 1);
158 blockDev
->flushCache(fd
);
163 // Formats sub partitions which are added to the main partition after it is initially
164 // formatted with PFS
165 int updateSuperBlock(pfs_mount_t
*pfsMount
, pfs_super_block
*superblock
, u32 sub
)
172 scale
= getScale(superblock
->zone_size
, 512);
173 count
= superblock
->num_subs
+ sub
+ 1;
175 for(i
= superblock
->num_subs
+ 1; i
< count
; i
++)
177 rv
= formatSub(pfsMount
->blockDev
, pfsMount
->fd
, i
, 1, scale
, 0);
182 superblock
->num_subs
= sub
;
184 // Write superblock, then write backup
185 rv
= pfsMount
->blockDev
->transfer(pfsMount
->fd
, superblock
, 0, PFS_SUPER_SECTOR
, 1, IOCTL2_TMODE_WRITE
);
187 rv
= pfsMount
->blockDev
->transfer(pfsMount
->fd
, superblock
, 0, PFS_SUPER_BACKUP_SECTOR
, 1, IOCTL2_TMODE_WRITE
);
189 pfsMount
->blockDev
->flushCache(pfsMount
->fd
);
194 int mountSuperBlock(pfs_mount_t
*pfsMount
)
198 pfs_super_block
*superblock
;
203 // Get number of sub partitions attached to the main partition
204 sub
= pfsMount
->blockDev
->getSubNumber(pfsMount
->fd
);
206 // Allocate a cache entry for the superblock
207 clink
= cacheAllocClean(&result
);
211 superblock
= clink
->u
.superblock
;
213 // Read the suprerblock from the main partition
214 result
= pfsMount
->blockDev
->transfer(pfsMount
->fd
, superblock
, 0, PFS_SUPER_SECTOR
, 1, IOCTL2_TMODE_READ
);
215 if(result
) goto error
;
217 if((superblock
->magic
!= PFS_SUPER_MAGIC
) || (superblock
->version
>= PFS_VERSION
))
219 printf("ps2fs: Error: Invalid magic/version\n");
224 if(!checkZoneSize(superblock
->zone_size
))
227 if((superblock
->fsckStat
& FSCK_STAT_WRITE_ERROR
) && (pfsMount
->flags
& FIO_ATTR_EXECUTABLE
))
230 if(sub
< superblock
->num_subs
)
232 printf("ps2fs: Error: Filesystem larger than partition\n");
236 if(result
) goto error
;
238 // If new subs have been added, update filesystem
239 if(superblock
->num_subs
< sub
)
241 dprintf("ps2fs: New subs added, updating filesystem..\n");
242 result
= updateSuperBlock(pfsMount
, superblock
, sub
);
245 if(result
) goto error
;
247 pfsMount
->zsize
= superblock
->zone_size
;
248 pfsMount
->sector_scale
= getScale(pfsMount
->zsize
, 512);
249 pfsMount
->inode_scale
= getScale(pfsMount
->zsize
, metaSize
);
250 pfsMount
->num_subs
= superblock
->num_subs
;
251 memcpy(&pfsMount
->root_dir
, &superblock
->root
, sizeof(pfs_blockinfo
));
252 memcpy(&pfsMount
->log
, &superblock
->log
, sizeof(pfs_blockinfo
));
253 memcpy(&pfsMount
->current_dir
, &superblock
->root
, sizeof(pfs_blockinfo
));
254 pfsMount
->total_sector
= 0;
258 // Do a journal restore (in case of un-clean unmount)
259 journalResetore(pfsMount
);
261 // Calculate free space and total size
262 for(i
= 0; i
< (pfsMount
->num_subs
+ 1); i
++)
266 pfsMount
->total_sector
+= pfsMount
->blockDev
->getSize(pfsMount
->fd
, i
) >> pfsMount
->sector_scale
;
268 free
= calcFreeZones(pfsMount
, i
);
269 pfsMount
->free_zone
[i
] = free
;
270 pfsMount
->zfree
+= free
;