revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-sam440 / boot / parthenope / src / sfs.c
blob82a597d91da1911b375b7f90a0660cdd9f00b5e4
1 /* ext2.c */
3 /* <project_name> -- <project_description>
5 * Copyright (C) 2006 - 2007
6 * Giuseppe Coviello <cjg@cruxppc.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "context.h"
24 #include "rdb.h"
25 #include "sfs.h"
27 typedef struct {
28 int (*load_file) (void *this, char *filename, void *buffer);
29 void (*destroy) (void *this);
30 struct RdbPartition *partition;
31 struct SfsObject *root;
32 uint32_t extentbnoderoot;
33 uint32_t blocksize;
34 } sfs_boot_dev_t;
36 uint32_t calcchecksum(struct SfsBlockHeader *block, uint32_t blocksize)
38 uint32_t *data = (uint32_t *) block;
39 uint32_t checksum = 1;
41 block->checksum = 0;
43 while (blocksize > 0) {
44 checksum += *data++;
45 blocksize -= 4;
48 return -checksum;
51 static int sfs_loadsector(sfs_boot_dev_t *self, uint32_t block, void *buffer)
53 return loadsector(self->partition->info->start
54 + (block * (self->blocksize / 512)),
55 self->partition->info->blksz, self->blocksize / 512,
56 buffer);
59 static struct SfsObject *sfs_nextobject(struct SfsObject *o)
61 int i;
62 uint8_t *p = o->name;
64 for (i = 2; i > 0; p++)
65 if (*p == '\0')
66 i--;
67 if ((p - (uint8_t *) o) & 0x01)
68 p++;
70 return ((struct SfsObject *)p);
73 static struct SfsObject *sfs_findobject(sfs_boot_dev_t * self,
74 struct SfsObject *cwd,
75 char *dirname, uint8_t type)
77 void *buffer;
78 uint32_t next;
79 struct SfsObject *o;
81 buffer = malloc(self->blocksize);
82 next = cwd->object.dir.firstdirblock;
84 while (next != 0) {
85 sfs_loadsector(self, next, buffer);
86 if (!calcchecksum(SBH(buffer), self->blocksize)) {
87 printf("Invalid checksum!\n");
88 return NULL;
90 if (SBH(buffer)->id != SOC_ID)
91 break;
92 o = SOC(buffer)->object;
93 while (o->objectnode > 0) {
94 if (strcasecmp((char *)o->name, dirname) == 0
95 && (!type || o->bits & type))
96 return o;
97 o = sfs_nextobject(o);
99 next = SOC(buffer)->next;
101 free(buffer);
102 return NULL;
105 static struct SfsObject *sfs_find(sfs_boot_dev_t * self, char *filename)
107 char *directory;
108 char *p;
109 struct SfsObject *root;
111 if (*filename == '/')
112 filename++;
114 directory = malloc(strlen(filename) + 1);
115 root = self->root;
116 while (root && (p = strchr(filename, '/')) != NULL) {
117 memmove(directory, filename, strlen(filename) - strlen(p));
118 directory[strlen(filename) - strlen(p)] = 0;
119 filename += strlen(directory) + 1;
120 root = sfs_findobject(self, root, directory, OTYPE_DIR);
123 free(directory);
125 if (root == NULL)
126 return NULL;
128 return sfs_findobject(self, root, filename, 0);
131 static struct BNode *get_bnode(sfs_boot_dev_t * self, uint32_t key)
133 void *buffer;
134 struct BNode *bnode, *tmp;
135 uint32_t next;
136 int i;
138 bnode = NULL;
139 buffer = malloc(self->blocksize);
140 next = self->extentbnoderoot;
141 while (sfs_loadsector(self, next, buffer)) {
142 if (!calcchecksum(SBH(buffer), self->blocksize)) {
143 printf("Invalid checksum!\n");
144 return NULL;
146 bnode = NULL;
147 for (i = SBNC(buffer)->btc.nodecount - 1; i >= 0; i--) {
148 tmp = (struct BNode *)(((uint8_t *) SBNC(buffer)->btc.
149 bnode) +
150 i * SBNC(buffer)->btc.nodesize);
151 if (tmp->key <= key) {
152 bnode = tmp;
153 break;
156 if (bnode == NULL)
157 return NULL;
158 if (SBNC(buffer)->btc.isleaf)
159 break;
160 next = bnode->data;
162 return bnode;
165 static int sfs_loadfile(sfs_boot_dev_t * self, char *filename, void *filebuffer)
167 struct SfsObject *o;
168 void *buffer;
169 uint32_t i, next, readed, size, tocopy;
170 struct SfsExtentBNode *sebn;
172 if ((o = sfs_find(self, filename)) == NULL) {
173 printf("%s not found!\n", filename);
174 return -1;
177 buffer = malloc(self->blocksize);
179 next = o->object.file.data;
180 size = o->object.file.size;
181 readed = 0;
182 while (next != 0 && readed < size) {
183 sebn = (struct SfsExtentBNode *)get_bnode(self, next);
184 for (i = 0; i < sebn->blocks; i++) {
185 sfs_loadsector(self, next + i, buffer);
186 tocopy = (size - readed >= self->blocksize
187 ? self->blocksize : size - readed);
188 if (filebuffer != NULL)
189 memmove(filebuffer + readed, buffer, tocopy);
190 readed += tocopy;
192 next = sebn->next;
194 free(buffer);
195 return readed;
198 static int sfs_destroy(sfs_boot_dev_t * this)
200 free(this);
201 return 0;
204 boot_dev_t *sfs_create(struct RdbPartition *partition)
206 sfs_boot_dev_t *boot;
207 void *buffer;
210 boot = malloc(sizeof(sfs_boot_dev_t));
211 boot->partition = partition;
213 buffer = malloc(64 * 512);
214 loadsector(boot->partition->info->start, boot->partition->info->blksz,
215 64, buffer);
216 if (SBH(buffer)->id != SRB_ID) {
217 printf("** Bad sfs partition or disk - %d:%d **\n",
218 boot->partition->disk, boot->partition->partition);
219 free(buffer);
220 free(boot);
221 return NULL;
224 boot->extentbnoderoot = SRB(buffer)->extentbnoderoot;
225 boot->blocksize = SRB(buffer)->blocksize;
227 sfs_loadsector(boot, SRB(buffer)->rootobjectcontainer, buffer);
229 if (SBH(buffer)->id != SOC_ID) {
230 printf("** Root Object Container not found - %d:%d **\n",
231 boot->partition->disk, boot->partition->partition);
232 free(buffer);
233 free(boot);
234 return NULL;
237 printf("Found sfs partition! Name: %s\n",
238 (char *)SOC(buffer)->object->name);
240 boot->root = malloc(sizeof(struct SfsObject));
241 memmove(boot->root, SOC(buffer)->object, sizeof(struct SfsObject));
242 free(buffer);
244 boot->load_file = (int (*)(void *, char *, void *))sfs_loadfile;
245 boot->destroy = (void (*)(void *))sfs_destroy;
247 return (boot_dev_t *) boot;