PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
superWrite.c
1/*
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.
9#
10# PFS superblock (write) manipulation routines
11*/
12
13#include <errno.h>
14#include <stdio.h>
15#ifdef _IOP
16#include <sysclib.h>
17#else
18#include <string.h>
19#endif
20#include <hdd-ioctl.h>
21
22#include "libpfs.h"
23
24extern u32 pfsBlockSize;
25extern u32 pfsMetaSize;
26
27// Formats a partition (main or sub) by filling with fragment pattern and setting the bitmap accordingly
28int pfsFormatSub(pfs_block_device_t *blockDev, int fd, u32 sub, u32 reserved, u32 scale, u32 fragment)
29{
30 pfs_cache_t *cache;
31 u32 sector, count, size;
32 int result = 0;
33
34 size = blockDev->getSize(fd, sub);
35 sector = 1 << scale;
36 count = pfsGetBitmapSizeSectors(scale, size);
37 if (reserved>=2)
38 sector+=0x2000;
39 reserved += pfsGetBitmapSizeBlocks(scale, size);
40
41 if((cache = pfsCacheAllocClean(&result)))
42 {
43 int i;
44 unsigned int j;
45 u32 *b;
46
47 // fill with fragment pattern
48 for (i=127; i>=0; i--)
49 cache->u.bitmap[i]=fragment;
50
51 // set as allocated the sectors up to reserved, for the first part of the bitmap
52 // this will mark the area the bitmaps themselves occupy as used
53 for (j=0, b=cache->u.bitmap; j<reserved; j++)
54 {
55 if (j && ((j & 0x1F)==0))
56 b++;
57 *b |= 1 << (j & 0x1F);
58 }
59
60 PFS_PRINTF(PFS_DRV_NAME": Format sub: sub = %ld, sector start = %ld, ", sub, sector);
61
62 // set the rest of the bitmap to the fragment
63 while (count-- && ((result=blockDev->transfer(fd, cache->u.bitmap, sub, sector++, 1, 1))>=0))
64 for (i=127; i>=0; i--)
65 cache->u.bitmap[i]=fragment;
66
67 PFS_PRINTF("sector end = %ld\n", sector - 1);
68
69 pfsCacheFree(cache);
70 }
71 return result;
72}
73
74// Formats a partition and all sub-partitions with PFS
75int pfsFormat(pfs_block_device_t *blockDev, int fd, int zonesize, int fragment)
76{
77 int result, result2;
78 pfs_cache_t *clink;
80 int scale;
81 u32 i, mainsize, subnumber = blockDev->getSubNumber(fd);
82
83 mainsize=blockDev->getSize(fd, 0);
84 if(pfsCheckZoneSize(zonesize) == 0)
85 return -EINVAL;
86
87 scale = pfsGetScale(zonesize, 512);
88
89 if((clink=pfsCacheAllocClean(&result)))
90 {
91 sb = clink->u.superblock;
92 memset(sb, 0, pfsMetaSize);
93 sb->magic = PFS_SUPER_MAGIC;
94 sb->version = PFS_FORMAT_VERSION;
95 sb->modver = ((PFS_MAJOR << 8) | PFS_MINOR);
96 sb->zone_size = zonesize;
97 sb->num_subs = subnumber;
98 sb->log.number = pfsGetBitmapSizeBlocks(scale, mainsize) + (0x2000 >> scale) + 1;
99 sb->log.count = (0x20000 / zonesize) ? (0x20000 / zonesize) : 1;
100
101 PFS_PRINTF(PFS_DRV_NAME": Format: log.number = %ld, log.count = %d\n", sb->log.number << scale, sb->log.count);
102
103 sb->root.count = 1;
104 sb->root.number = sb->log.number + sb->log.count;
105 if((result = pfsJournalResetThis(blockDev, fd, sb->log.number<<scale)) >= 0)
106 {
107 pfs_cache_t *cache;
108 if((cache = pfsCacheAllocClean(&result2)))
109 {
110 pfsFillSelfAndParentDentries(cache, &sb->root, &sb->root);
111 result2 = blockDev->transfer(fd, cache->u.dentry, 0, (sb->root.number+1) << scale,
112 1 << pfsBlockSize, 1);
113 if(result2 == 0)
114 {
115 // setup root directory
116 pfsInodeFill(cache, &sb->root, 0x11FF, 0, 0);
117 cache->u.inode->data[1].subpart = 0;
118 cache->u.inode->data[1].number = sb->root.number + 1;
119 cache->u.inode->data[1].count = 1;
120 cache->u.inode->checksum = pfsInodeCheckSum(cache->u.inode);
121
122 result2=blockDev->transfer(fd, cache->u.inode, 0, sb->root.number << scale,
123 1 << pfsBlockSize, 1);
124 }
125
126 pfsCacheFree(cache);
127 }
128
129 if((result = result2) >= 0)
130 {
131 for (i=0; i < subnumber+1; i++)
132 if((result=pfsFormatSub(blockDev, fd, i, i ? 1 : (0x2000 >> scale) +
133 sb->log.count + 3, scale, fragment))<0)
134 break;
135
136 if((result == 0) && ((result = blockDev->transfer(fd, sb, 0, PFS_SUPER_BACKUP_SECTOR, 1, 1))==0))
137 result = blockDev->transfer(fd, sb, 0, PFS_SUPER_SECTOR, 1, 1);
138 }
139 }
140
141 pfsCacheFree(clink);
142 blockDev->flushCache(fd);
143 }
144 return result;
145}
146
147// Formats sub partitions which are added to the main partition after it is initially
148// formatted with PFS
149int pfsUpdateSuperBlock(pfs_mount_t *pfsMount, pfs_super_block_t *superblock, u32 sub)
150{
151 u32 scale;
152 u32 i;
153 int rv;
154
155 scale = pfsGetScale(superblock->zone_size, 512);
156
157 for(i = superblock->num_subs + 1; i < sub + 1; i++)
158 {
159 rv = pfsFormatSub(pfsMount->blockDev, pfsMount->fd, i, 1, scale, 0);
160 if(rv < 0)
161 return rv;
162 }
163
164 superblock->num_subs = sub;
165
166 // Write superblock, then write backup
167 rv = pfsMount->blockDev->transfer(pfsMount->fd, superblock, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_WRITE);
168 if(!rv)
169 rv = pfsMount->blockDev->transfer(pfsMount->fd, superblock, 0, PFS_SUPER_BACKUP_SECTOR, 1, PFS_IO_MODE_WRITE);
170
171 pfsMount->blockDev->flushCache(pfsMount->fd);
172
173 return rv;
174}
175
176int pfsMountSuperBlock(pfs_mount_t *pfsMount)
177{
178 int result;
179 pfs_cache_t *clink;
180 pfs_super_block_t *superblock;
181 u32 sub;
182 u32 i;
183
184
185 // Get number of sub partitions attached to the main partition
186 sub = pfsMount->blockDev->getSubNumber(pfsMount->fd);
187
188 // Allocate a cache entry for the superblock
189 clink = pfsCacheAllocClean(&result);
190 if(!clink)
191 return result;
192
193 superblock = clink->u.superblock;
194
195 // Read the suprerblock from the main partition
196 result = pfsMount->blockDev->transfer(pfsMount->fd, superblock, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_READ);
197 if(result) goto error;
198
199 if((superblock->magic != PFS_SUPER_MAGIC) || (superblock->version > PFS_FORMAT_VERSION))
200 {
201 PFS_PRINTF(PFS_DRV_NAME": Error: Invalid magic/version\n");
202 pfsCacheFree(clink);
203 return -EIO;
204 }
205
206
207#ifdef PFS_SUPPORT_BHDD
208 if (strcmp(pfsMount->blockDev->devName, "bhdd") == 0)
209 {
210 if(!pfsCheckExtendedZoneSize(superblock->zone_size))
211 result = -EIO;
212 }
213 else
214#endif
215 {
216 if(!pfsCheckZoneSize(superblock->zone_size))
217 result = -EIO;
218 }
219
220 if((superblock->pfsFsckStat & PFS_FSCK_STAT_WRITE_ERROR) && (pfsMount->flags & PFS_FIO_ATTR_EXECUTABLE))
221 result = -EIO;
222
223 if(sub < superblock->num_subs)
224 {
225 PFS_PRINTF(PFS_DRV_NAME": Error: Filesystem larger than partition\n");
226 result = -EIO;
227 }
228
229 if(result) goto error;
230
231 // If new subs have been added, update filesystem
232 if(superblock->num_subs < sub)
233 {
234 PFS_PRINTF(PFS_DRV_NAME": New subs added, updating filesystem..\n");
235 result = pfsUpdateSuperBlock(pfsMount, superblock, sub);
236 }
237
238 if(result) goto error;
239
240 pfsMount->zsize = superblock->zone_size;
241 pfsMount->sector_scale = pfsGetScale(pfsMount->zsize, 512);
242 pfsMount->inode_scale = pfsGetScale(pfsMount->zsize, pfsMetaSize);
243 pfsMount->num_subs = superblock->num_subs;
244 memcpy(&pfsMount->root_dir, &superblock->root, sizeof(pfs_blockinfo_t));
245 memcpy(&pfsMount->log, &superblock->log, sizeof(pfs_blockinfo_t));
246 memcpy(&pfsMount->current_dir, &superblock->root, sizeof(pfs_blockinfo_t));
247 pfsMount->total_zones = 0;
248
249 // Do a journal restore (in case of un-clean unmount)
250 pfsJournalRestore(pfsMount);
251
252 // Calculate free space and total size
253 for(i = 0; i < (pfsMount->num_subs + 1); i++)
254 {
255 int free;
256
257 pfsMount->total_zones += pfsMount->blockDev->getSize(pfsMount->fd, i) >> pfsMount->sector_scale;
258
259 free = pfsBitmapCalcFreeZones(pfsMount, i);
260 pfsMount->free_zone[i] = free;
261 pfsMount->zfree += free;
262 }
263
264error:
265 pfsCacheFree(clink);
266 return result;
267}
#define EINVAL
Definition errno.h:63
#define EIO
Definition errno.h:29
u32 count
start sector of fragmented bd/file