ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
libhdd.c
Go to the documentation of this file.
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 
11 #include <stdio.h>
12 #include <tamtypes.h>
13 #include <errno.h>
14 #include <kernel.h>
15 #include <string.h>
16 #include <sifrpc.h>
17 #include <loadfile.h>
18 #include <iopheap.h>
19 #include <malloc.h>
20 
21 // PS2DRV includes
22 #include "sys/fcntl.h"
23 #include "sys/stat.h"
24 #include "sys/ioctl.h"
25 #include "errno.h"
26 
27 #include "libhdd.h"
28 
29 #define NEWLIB_PORT_AWARE
30 #include "fileXio_rpc.h"
31 #include "io_common.h"
32 
33 #define PFS_ZONE_SIZE 8192
34 #define PFS_FRAGMENT_OPT 0x00002d66 //"-f"
35 #define PFS_FRAGMENT 0x00000000
36 
37 #if (PFS_FRAGMENT != 0)
39 #else
40 static int pfsFormatArg[1] = { PFS_ZONE_SIZE };
41 #endif
42 
43 #define _OMIT_SYSTEM_PARTITION
44 //#define DEBUG
45 
46 static char *sizesString[9] = {
47  "128M",
48  "256M",
49  "512M",
50  "1G",
51  "2G",
52  "4G",
53  "8G",
54  "16G",
55  "32G"
56 };
57 
58 static int sizesMB[9] = {
59  128,
60  256,
61  512,
62  1024,
63  2048,
64  4096,
65  8192,
66  16384,
67  32768
68 };
69 
70 static void hddUpdateInfo();
71 
72 static int hddStatusCurrent = 0;
74 
76 {
77  int rv;
78 
79  if(!hddStatusCurrent)
80  hddUpdateInfo();
81 
82  rv = fileXioDevctl("hdd0:", HDIOC_STATUS, NULL, 0, NULL, 0);
83 
84  if((rv >= 3) || (rv < 0))
85  return -1;
86  else
87  return 0;
88 }
89 
91 {
92  int rv;
93 
94  if(!hddStatusCurrent)
95  hddUpdateInfo();
96 
97  rv = fileXioDevctl("hdd0:", HDIOC_STATUS, NULL, 0, NULL, 0);
98  if((rv >= 1) || (rv < 0))
99  return -1;
100  else
101  return 0;
102 }
103 
104 
106 {
107  int retVal, i;
108  const char *partitionList[] = {
109  "hdd0:__net",
110  "hdd0:__system",
111  "hdd0:__sysconf",
112  "hdd0:__common",
113  NULL
114  };
115 
116  if(!hddStatusCurrent)
117  hddUpdateInfo();
118 
119  retVal = fileXioFormat("hdd0:", NULL, NULL, 0);
120  if(retVal < 0)
121  return retVal;
122 
123  for(i = 0; partitionList[i] != NULL; i++)
124  {
125  retVal = fileXioFormat("pfs:", partitionList[i], (const char*)&pfsFormatArg, sizeof(pfsFormatArg));
126  if(retVal < 0)
127  return retVal;
128  }
129 
130  hddUpdateInfo();
131 
132  return 0;
133 }
134 
135 int hddGetFilesystemList(t_hddFilesystem hddFs[], int maxEntries)
136 {
137  iox_dirent_t dirEnt;
138  int count = 0;
139  u32 size = 0;
140  int hddFd;
141  int rv;
142 
143  if(!hddStatusCurrent)
144  hddUpdateInfo();
145 
146  hddFd = fileXioDopen("hdd0:");
147 
148  if(hddFd < 0)
149  return hddFd;
150 
151  rv = fileXioDread(hddFd, &dirEnt);
152 
153  while((rv > 0) && (count < maxEntries))
154  {
155  int i;
156  int partitionFd;
157  u32 zoneFree, zoneSize;
158 
159  // We only want to know about main partitions (non-empty ones at that :P)
160  if((dirEnt.stat.attr & ATTR_SUB_PARTITION) || (dirEnt.stat.mode == FS_TYPE_EMPTY))
161  {
162  rv = fileXioDread(hddFd, &dirEnt);
163  continue;
164  }
165 
166  memset(&hddFs[count], 0, sizeof(t_hddFilesystem));
167  snprintf(hddFs[count].filename, 40, "hdd0:%.34s", dirEnt.name);
168 
169  // Work out filesystem type
170  if((dirEnt.name[0] == '_') && (dirEnt.name[1] == '_'))
171  {
172  hddFs[count].fileSystemGroup = FS_GROUP_SYSTEM;
173  strcpy(hddFs[count].name, &dirEnt.name[2]);
174  }
175  else if(dirEnt.name[0] == FS_COMMON_PREFIX)
176  {
177  hddFs[count].fileSystemGroup = FS_GROUP_COMMON;
178  strcpy(hddFs[count].name, &dirEnt.name[1]);
179  }
180  else
181  {
182  hddFs[count].fileSystemGroup = FS_GROUP_APPLICATION;
183  strcpy(hddFs[count].name, dirEnt.name);
184  }
185 
186 #ifdef _OMIT_SYSTEM_PARTITION
187  if(hddFs[count].fileSystemGroup == FS_GROUP_SYSTEM)
188  {
189  rv = fileXioDread(hddFd, &dirEnt);
190  continue;
191  }
192 #endif
193 
194 #ifdef DEBUG
195  printf("> Filename: %s\n> Name: %s\n> Type: %d\n", hddFs[count].filename, hddFs[count].name, hddFs[count].fileSystemGroup);
196 #endif
197 
198  // Calculate filesystem size
199  partitionFd = fileXioOpen(hddFs[count].filename, FIO_O_RDONLY);
200 
201  // If we failed to open the partition, then a password is probably set
202  // (usually this means we have tried to access a game partition). We
203  // dont want to return un-accessible game partitions in the filesystem list..
204  if(partitionFd < 0)
205  {
206  rv = fileXioDread(hddFd, &dirEnt);
207  continue;
208  }
209 
210  for(i = 0, size = 0; i < dirEnt.stat.private_0 + 1; i++)
211  {
212  rv = fileXioIoctl2(partitionFd, HIOCGETSIZE, &i, 4, NULL, 0);
213  size += (u32)rv / 2048; //Equal to, but avoids overflows of: rv * 512 / 1024 / 1024;
214  }
215 
216  fileXioClose(partitionFd);
217 
218  hddFs[count].size = size;
219 
220  // Get filesystem free space & format status
221  hddFs[count].freeSpace = 0;
222  hddFs[count].formatted = 0;
223 
224  if(dirEnt.stat.mode == FS_TYPE_PFS)
225  {
226  rv = fileXioMount("pfs0:", hddFs[count].filename, FIO_MT_RDONLY);
227  if(rv == 0)
228  {
229 
230  zoneFree = fileXioDevctl("pfs0:", PDIOC_ZONEFREE, NULL, 0, NULL, 0);
231  zoneSize = fileXioDevctl("pfs0:", PDIOC_ZONESZ, NULL, 0, NULL, 0);
232 
233  hddFs[count].freeSpace = zoneFree * zoneSize / 1024 / 1024;
234  hddFs[count].formatted = 1;
235 
236  fileXioUmount("pfs0:");
237  }
238  }
239 
240 #ifdef DEBUG
241  printf("> Formatted: %d\n> Size: %d\n> Free: %d\n", hddFs[count].formatted, (int)hddFs[count].size, (int)hddFs[count].freeSpace);
242 #endif
243 
244  count++;
245  rv = fileXioDread(hddFd, &dirEnt);
246  }
247 
248  rv = fileXioDclose(hddFd);
249 
250  return count;
251 }
252 
254 {
255  hddUpdateInfo();
256 
257  info->hddSize = hddSize;
258  info->hddFree = hddFree;
259  info->hddMaxPartitionSize = hddMaxPartitionSize;
260 }
261 
262 static void hddUpdateInfo()
263 {
264  iox_dirent_t infoDirEnt;
265  int rv;
266  int hddFd;
267  u32 hddUsed = 0;
268 
269  hddSize = (u32)fileXioDevctl("hdd0:", HDIOC_TOTALSECTOR, NULL, 0, NULL, 0) / 2048; //sectors * 512 / 1024 / 1024;
270 
271 /* This gives inaccurate results, due to it being an approximation.
272  fileXioDevctl("hdd0:", HDIOC_FREESECTOR, NULL, 0, &rv, 4);
273  hddFree = rv * 512 / 1024 / 1024;
274 */
275  hddFd = fileXioDopen("hdd0:");
276  if(hddFd < 0) // For when a HDD is not connected!
277  return;
278 
279  rv = fileXioDread(hddFd, &infoDirEnt);
280  while(rv > 0)
281  {
282  if(infoDirEnt.stat.mode != FS_TYPE_EMPTY)
283  hddUsed += infoDirEnt.stat.size / 2048; //Equal to, but avoids overflows of: infoDirEnt.stat.size * 512 / 1024 / 1024;
284 
285  rv = fileXioDread(hddFd, &infoDirEnt);
286  }
287  fileXioDclose(hddFd);
288  hddFree = hddSize - hddUsed;
289 
290  hddMaxPartitionSize = (u32)fileXioDevctl("hdd0:", HDIOC_MAXSECTOR, NULL, 0, NULL, 0) / 2048; //Equal to, but avoids overflows of: sectors * 512 / 1024 / 1024;
291 
292  hddStatusCurrent = 1;
293 }
294 
295 int hddMakeFilesystem(int fsSizeMB, char *name, int type)
296 {
297  int maxIndex;
298  int useIndex;
299  int partSize;
300  int fsSizeLeft = fsSizeMB;
301  int partFd;
302  char openString[256];
303  char fsName[256];
304  int retVal;
305 
306  if(!hddStatusCurrent)
307  hddUpdateInfo();
308 
309  if(fsSizeMB % 128)
310  return -EINVAL;
311 
312  switch(type)
313  {
314  case FS_GROUP_SYSTEM:
315  sprintf(fsName, "__%s", name);
316  break;
317  case FS_GROUP_COMMON:
318  sprintf(fsName, "+%s", name);
319  break;
320  default:
321  strcpy(fsName, name);
322  break;
323  }
324 
325  // Check if filesystem already exists
326  sprintf(openString, "hdd0:%s", fsName);
327  partFd = fileXioOpen(openString, FIO_O_RDONLY);
328  if(partFd > 0 || partFd == -EACCES) // Filesystem already exists
329  {
330  fileXioClose(partFd);
331  return -1;
332  }
333 
334  // Get index for max partition size
335  for(maxIndex = 0; maxIndex < 9; maxIndex++)
336  if(sizesMB[maxIndex] == hddMaxPartitionSize)
337  break;
338 
339  // Get index of size we will use to create main partition
340  for(useIndex = maxIndex; sizesMB[useIndex] > fsSizeMB; useIndex--);
341 
342  for(partSize = sizesMB[useIndex]; useIndex >= 0; useIndex--,partSize = sizesMB[useIndex])
343  {
344 #ifdef DEBUG
345  printf(">>> Attempting to create main partition, size %d MB\n", partSize);
346 #endif
347 
348  sprintf(openString, "hdd0:%s,,,%s,PFS", fsName, sizesString[useIndex]);
349 #ifdef DEBUG
350  printf(">>> openString = %s\n", openString);
351 #endif
352 
353  partFd = fileXioOpen(openString, FIO_O_RDWR | FIO_O_CREAT);
354  if(partFd >= 0)
355  break;
356  else {
357  if(partFd != -ENOSPC)
358  {
359 #ifdef DEBUG
360  printf(">>> Could not create Main Partition (error %d)!\n", partFd);
361 #endif
362  return partFd;
363  }
364  }
365  }
366 
367  if(useIndex < 0)
368  {
369 #ifdef DEBUG
370  printf(">>> Could not create Main Partition (no space)!\n");
371 #endif
372  return -ENOSPC;
373  }
374 
375  fsSizeLeft -= partSize;
376 #ifdef DEBUG
377  printf(">>> Main partition of %d MB created!\n", partSize);
378 #endif
379 
380  while(fsSizeLeft)
381  {
382 
383  // Adjust size if necessary
384  if(fsSizeLeft < partSize)
385  {
386 #ifdef DEBUG
387  printf(">>> Adjusting sub size: %d MB to ", sizesMB[useIndex]);
388 #endif
389  for(useIndex = maxIndex; sizesMB[useIndex] > fsSizeLeft; useIndex--);
390  partSize = sizesMB[useIndex];
391  maxIndex = useIndex;
392 #ifdef DEBUG
393  printf("%d MB\n", sizesMB[useIndex]);
394 #endif
395  }
396 
397  // Try and allocate sub
398 #ifdef DEBUG
399  printf(">>> Attempting to create sub partition of size %d MB\n", sizesMB[useIndex]);
400 #endif
401  retVal = fileXioIoctl2(partFd, HIOCADDSUB, sizesString[useIndex], strlen(sizesString[useIndex]) + 1, NULL, 0);
402  if(retVal == -ENOSPC)
403  {
404  // If sub alloc fails due to size, we decrease size and try again.
405  // If we've run out of sizes, break the loop (give up)
406  useIndex--;
407  partSize = sizesMB[useIndex];
408  maxIndex = useIndex;
409 
410  if(useIndex < 0)
411  {
412 #ifdef DEBUG
413  printf(">>> Out of sizes to try. Giving up.\n");
414 #endif
415  break;
416  }
417 #ifdef DEBUG
418  printf(">>> Subpartition alloc FAILED! Trying with size of %d MB\n", partSize);
419 #endif
420 
421  continue;
422  }
423  // If we've reached the max number of subs, bail.
424  else if(retVal == -EFBIG)
425  break;
426  else if(retVal >= 0)
427  {
428 #ifdef DEBUG
429  printf(">>> Sub creation successfull!\n");
430 #endif
431  }
432  else
433  {
434 #ifdef DEBUG
435  printf(">>> Unknown error while creating sub: %d\n", retVal);
436 #endif
437  }
438 
439  fsSizeLeft -= sizesMB[useIndex];
440  }
441 
442  fileXioClose(partFd);
443 
444  sprintf(openString, "hdd0:%s", fsName);
445  retVal = fileXioFormat("pfs:", openString, (const char*)&pfsFormatArg, sizeof(pfsFormatArg));
446  if(retVal < 0)
447  {
448 #ifdef DEBUG
449  printf(">>> Failed to format new partition: %d\n", retVal);
450 #endif
451  return retVal;
452  }
453 
454  hddUpdateInfo();
455 
456  return fsSizeMB - fsSizeLeft;
457 }
458 
460 {
461  int rv;
462 
463  if(!hddStatusCurrent)
464  hddUpdateInfo();
465 
466  rv = fileXioRemove(fs->filename);
467 
468  hddUpdateInfo();
469 
470  return rv;
471 }
472 
474 {
475  int maxIndex;
476  int useIndex;
477  int partSize;
478  int fsSizeLeft = extraMB;
479  int partFd;
480  int retVal;
481 
482  if(!hddStatusCurrent)
483  hddUpdateInfo();
484 
485  if(extraMB % 128)
486  return -EINVAL;
487 
488  // Get index for max partition size
489  for(maxIndex = 0; maxIndex < 9; maxIndex++)
490  if(sizesMB[maxIndex] == hddMaxPartitionSize)
491  break;
492 
493  // Get index of size we will use to create new subs
494  for(useIndex = maxIndex; sizesMB[useIndex] > extraMB; useIndex--);
495 
496  partSize = sizesMB[useIndex];
497 
498  // Open partition
499  partFd = fileXioOpen(fs->filename, FIO_O_RDWR);
500  if(partFd < 0)
501  return partFd;
502 
503  while(fsSizeLeft)
504  {
505  // Adjust size if necessary
506  if(fsSizeLeft < partSize)
507  {
508 #ifdef DEBUG
509  printf(">>> Adjusting sub size: %d MB to ", sizesMB[useIndex]);
510 #endif
511  for(useIndex = maxIndex; sizesMB[useIndex] > fsSizeLeft; useIndex--);
512  partSize = sizesMB[useIndex];
513  maxIndex = useIndex;
514 #ifdef DEBUG
515  printf("%d MB\n", sizesMB[useIndex]);
516 #endif
517  }
518 
519  // Try and allocate new sub
520 #ifdef DEBUG
521  printf(">>> Attempting to create sub partition of size %d MB\n", sizesMB[useIndex]);
522 #endif
523  retVal = fileXioIoctl2(partFd, HIOCADDSUB, sizesString[useIndex], strlen(sizesString[useIndex]) + 1, NULL, 0);
524  if(retVal == -ENOSPC)
525  {
526  // If sub alloc fails due to size, we decrease size and try again.
527  // If we've run out of sizes, break the loop (give up)
528  useIndex--;
529  partSize = sizesMB[useIndex];
530  maxIndex = useIndex;
531 
532  if(useIndex < 0)
533  {
534 #ifdef DEBUG
535  printf(">>> Out of sizes to try. Giving up.\n");
536 #endif
537  break;
538  }
539 #ifdef DEBUG
540  printf(">>> Subpartition alloc FAILED! Trying with size of %d MB\n", partSize);
541 #endif
542 
543  continue;
544  }
545  // If we've reached the max number of subs, bail.
546  else if(retVal == -EFBIG)
547  break;
548  else if(retVal >= 0)
549  {
550 #ifdef DEBUG
551  printf(">>> Sub creation successfull!\n");
552 #endif
553  }
554  else
555  {
556 #ifdef DEBUG
557  printf(">>> Unknown error while creating sub: %d\n", retVal);
558 #endif
559  }
560 
561  fsSizeLeft -= sizesMB[useIndex];
562  }
563 
564  fileXioClose(partFd);
565 
566  hddUpdateInfo();
567 
568  return extraMB - fsSizeLeft;
569 }
jpgData * info
Definition: camera-test.c:14
#define ENOSPC
Definition: errno.h:74
#define EINVAL
Definition: errno.h:62
#define EACCES
Definition: errno.h:44
#define EFBIG
Definition: errno.h:72
int fileXioDread(int fd, iox_dirent_t *dirent)
Definition: fileXio_rpc.c:948
int fileXioClose(int fd)
Definition: fileXio_rpc.c:612
int fileXioDevctl(const char *name, int cmd, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
Definition: fileXio_rpc.c:986
int fileXioMount(const char *mountpoint, const char *blockdev, int flag)
Definition: fileXio_rpc.c:319
int fileXioRemove(const char *pathname)
Definition: fileXio_rpc.c:449
int fileXioDclose(int fd)
Definition: fileXio_rpc.c:924
int fileXioDopen(const char *name)
Definition: fileXio_rpc.c:900
int fileXioUmount(const char *mountpoint)
Definition: fileXio_rpc.c:346
int fileXioIoctl2(int fd, int command, void *arg, unsigned int arglen, void *buf, unsigned int buflen)
Definition: fileXio_rpc.c:1055
int fileXioOpen(const char *source, int flags,...)
Definition: fileXio_rpc.c:581
int fileXioFormat(const char *dev, const char *blockdev, const void *args, int arglen)
Definition: fileXio_rpc.c:843
#define HDIOC_TOTALSECTOR
Definition: hdd-ioctl.h:92
#define HIOCGETSIZE
Definition: hdd-ioctl.h:62
#define HDIOC_STATUS
Definition: hdd-ioctl.h:97
#define HIOCADDSUB
Definition: hdd-ioctl.h:53
#define PDIOC_ZONESZ
Definition: hdd-ioctl.h:198
#define PDIOC_ZONEFREE
Definition: hdd-ioctl.h:199
#define HDIOC_MAXSECTOR
Definition: hdd-ioctl.h:90
#define FIO_MT_RDONLY
Definition: io_common.h:41
#define FIO_O_CREAT
Definition: io_common.h:35
#define FIO_O_RDWR
Definition: io_common.h:31
#define FIO_O_RDONLY
Definition: io_common.h:29
static int sizesMB[9]
Definition: libhdd.c:58
int hddExpandFilesystem(t_hddFilesystem *fs, int extraMB)
Definition: libhdd.c:473
int hddRemoveFilesystem(t_hddFilesystem *fs)
Definition: libhdd.c:459
static int pfsFormatArg[1]
Definition: libhdd.c:40
int hddFormat()
Definition: libhdd.c:105
static char * sizesString[9]
Definition: libhdd.c:46
static u32 hddFree
Definition: libhdd.c:73
int hddGetFilesystemList(t_hddFilesystem hddFs[], int maxEntries)
Definition: libhdd.c:135
int hddMakeFilesystem(int fsSizeMB, char *name, int type)
Definition: libhdd.c:295
int hddCheckPresent()
Definition: libhdd.c:75
void hddGetInfo(t_hddInfo *info)
Definition: libhdd.c:253
static int hddStatusCurrent
Definition: libhdd.c:72
#define PFS_ZONE_SIZE
Definition: libhdd.c:33
#define PFS_FRAGMENT
Definition: libhdd.c:35
static u32 hddSize
Definition: libhdd.c:73
#define PFS_FRAGMENT_OPT
Definition: libhdd.c:34
static void hddUpdateInfo()
Definition: libhdd.c:262
static u32 hddMaxPartitionSize
Definition: libhdd.c:73
int hddCheckFormatted()
Definition: libhdd.c:90
#define FS_GROUP_COMMON
Definition: libhdd.h:28
#define FS_TYPE_EMPTY
Definition: libhdd.h:34
#define FS_GROUP_SYSTEM
Definition: libhdd.h:27
#define FS_COMMON_PREFIX
Definition: libhdd.h:25
#define ATTR_SUB_PARTITION
Definition: libhdd.h:37
#define FS_GROUP_APPLICATION
Definition: libhdd.h:29
#define FS_TYPE_PFS
Definition: libhdd.h:33
char name[256]
Definition: iox_stat.h:112
iox_stat_t stat
Definition: iox_stat.h:111
unsigned int private_0
Definition: iox_stat.h:101
unsigned int attr
Definition: iox_stat.h:94
unsigned int size
Definition: iox_stat.h:95
unsigned int mode
Definition: iox_stat.h:93
char filename[40]
Definition: libhdd.h:43
u32 freeSpace
Definition: libhdd.h:49
int formatted
Definition: libhdd.h:47
int fileSystemGroup
Definition: libhdd.h:51
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30