4 #define GETSHORT(p) (*(ushort *)(p))
5 #define GETLONG(p) (*(uint *)(p))
16 typedef struct File File;
17 typedef struct Dir Dir;
18 typedef struct Pbs Pbs;
19 typedef struct Fat Fat;
29 ulong dirstart; /* LBA for FAT16, cluster for FAT32 */
108 int readsect(ulong drive, ulong lba, void *buf);
116 readnext(File *fp, ulong clust)
122 sect = clust * b / Sectsz;
123 off = clust * b % Sectsz;
124 if(readsect(fat->drive, fat->fatlba + sect, fp->buf))
125 memset(fp->buf, 0xff, 4);
128 return GETSHORT(&fp->buf[off]);
130 return GETLONG(&fp->buf[off])& 0x0fffffff;
136 read(void *f, void *data, int len)
141 if(fp->len > 0 && fp->rp >= fp->ep){
142 if(fp->clust != ~0U){
143 if(fp->lbaoff % fat->clustsize == 0){
144 if((fp->clust >> 4) == fat->eofmark)
146 fp->lbaoff = (fp->clust - 2) * fat->clustsize;
147 fp->clust = readnext(fp, fp->clust);
148 fp->lba = fp->lbaoff + fat->datalba;
152 if(readsect(fat->drive, fp->lba++, fp->rp = fp->buf))
157 if(len > (fp->ep - fp->rp))
158 len = fp->ep - fp->rp;
159 memmove(data, fp->rp, len);
171 dirname(Dir *d, char buf[Maxpath])
175 if(d->attr == 0x0F || *d->name <= 0)
177 memmove(buf, d->name, 8);
179 while(x > buf && x[-1] == ' ')
181 if(d->name[8] != ' '){
183 memmove(x, d->name+8, 3);
186 while(x > buf && x[-1] == ' ')
191 if(c >= 'A' && c <= 'Z'){
203 return *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo);
207 fileinit(File *fp, Fat *fat, ulong lba)
214 fp->rp = fp->ep = fp->buf + Sectsz;
218 fatwalk(File *fp, Fat *fat, char *path)
220 char name[Maxpath], *end;
224 if(fat->ver == Fat32){
225 fileinit(fp, fat, 0);
226 fp->clust = fat->dirstart;
229 fileinit(fp, fat, fat->dirstart);
230 fp->len = fat->dirents * Dirsz;
233 if(readn(fp, &d, Dirsz) != Dirsz)
235 if((i = dirname(&d, name)) <= 0)
239 if((end = strchr(path, '/')) == 0)
240 end = path + strlen(path);
242 if(i == j && memcmp(name, path, j) == 0){
243 fileinit(fp, fat, 0);
244 fp->clust = dirclust(&d);
245 fp->len = *((ulong*)d.len);
248 else if(d.attr & 0x10){
249 fp->len = fat->clustsize * Sectsz;
260 conffat(Fat *fat, void *buf)
263 uint fatsize, volsize, datasize, reserved;
264 uint ver, dirsize, dirents, clusters;
267 if(GETSHORT(p->sectsize) != Sectsz){
268 print("sectsize != 512\r\n");
272 /* load values from fat */
273 fatsize = GETSHORT(p->fatsize);
275 fatsize = GETLONG(p->fat32.fatsize);
276 volsize = GETSHORT(p->volsize);
278 volsize = GETLONG(p->bigvolsize);
279 reserved = GETSHORT(p->nreserv);
280 dirents = GETSHORT(p->rootsize);
281 dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
282 datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
283 clusters = datasize / p->clustsize;
285 /* determine fat type */
288 else if(clusters < 65525)
295 print("TODO: implement FAT12\r\n");
299 /* fill FAT descriptor */
301 fat->dirents = dirents;
302 fat->clustsize = p->clustsize;
303 fat->fatlba = fat->partlba + reserved;
304 fat->dirstart = fat->fatlba + fatsize * p->nfats;
306 fat->datalba = fat->dirstart;
307 fat->dirstart = GETLONG(p->fat32.rootclust);
308 fat->eofmark = 0xffffff;
310 fat->datalba = fat->dirstart + dirsize;
311 fat->eofmark = 0xfff;
317 findfat(Fat *fat, int drive)
330 if(readsect(drive, 0, buf))
332 if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
334 p = (void*)&buf[0x1be];
336 if(p[i].status != 0x80)
339 fat->partlba = *((ulong*)p[i].lba);
340 if(readsect(drive, fat->partlba, buf))
342 if(conffat(fat, buf))
352 char path[Maxpath], *kern;
358 /* drive passed in DL */
359 drive = ((ushort*)sp)[5] & 0xFF;
361 print("9bootfat\r\n");
362 if(findfat(&fat, drive)){
366 if(fatwalk(f = &fi, &fat, "plan9.ini")){
367 print("no config\r\n");
371 kern = configure(f, path); f = 0;
372 if(fatwalk(&fi, &fat, kern)){
373 print("not found\r\n");
376 print(bootkern(&fi));