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 Pbs32 Pbs32;
20 typedef struct Fat Fat;
30 ulong dirstart; /* LBA for FAT16, cluster for FAT32 */
105 int readsect(ulong drive, ulong lba, void *buf);
113 readnext(File *fp, ulong clust)
119 if(fat->ver == Fat12)
122 idx = clust*fat->ver;
123 lba = fat->fatlba + (idx / Sectsz);
124 if(readsect(fat->drive, lba, fp->buf))
125 memset(fp->buf, 0xff, Sectsz);
126 p = &fp->buf[idx % Sectsz];
127 if(p == &fp->buf[Sectsz-1]){
129 if(readsect(fat->drive, ++lba, fp->buf))
130 memset(fp->buf, 0xff, Sectsz);
134 if(fat->ver == Fat32)
135 return GETLONG(p) & 0xfffffff;
137 if(fat->ver == Fat12){
146 read(void *f, void *data, int len)
151 if(fp->len > 0 && fp->rp >= fp->ep){
152 if(fp->clust != ~0U){
153 if(fp->lbaoff % fat->clustsize == 0){
154 if(fp->clust < 2 || fp->clust >= fat->eofmark)
156 fp->lbaoff = (fp->clust - 2) * fat->clustsize;
157 fp->clust = readnext(fp, fp->clust);
158 fp->lba = fp->lbaoff + fat->datalba;
162 if(readsect(fat->drive, fp->lba++, fp->rp = fp->buf))
167 if(len > (fp->ep - fp->rp))
168 len = fp->ep - fp->rp;
169 memmove(data, fp->rp, len);
181 dirname(Dir *d, char buf[Maxpath])
185 if(d->attr == 0x0F || *d->name <= 0)
187 memmove(buf, d->name, 8);
189 while(x > buf && x[-1] == ' ')
191 if(d->name[8] != ' '){
193 memmove(x, d->name+8, 3);
196 while(x > buf && x[-1] == ' ')
201 if(c >= 'A' && c <= 'Z'){
213 return *((ushort*)d->starthi)<<16 | *((ushort*)d->startlo);
217 fileinit(File *fp, Fat *fat, ulong lba)
224 fp->rp = fp->ep = fp->buf + Sectsz;
228 fatwalk(File *fp, Fat *fat, char *path)
230 char name[Maxpath], *end;
234 if(fat->ver == Fat32){
235 fileinit(fp, fat, 0);
236 fp->clust = fat->dirstart;
239 fileinit(fp, fat, fat->dirstart);
240 fp->len = fat->dirents * Dirsz;
243 if(readn(fp, &d, Dirsz) != Dirsz)
245 if((i = dirname(&d, name)) <= 0)
249 if((end = strchr(path, '/')) == 0)
250 end = path + strlen(path);
252 if(i == j && memcmp(name, path, j) == 0){
253 fileinit(fp, fat, 0);
254 fp->clust = dirclust(&d);
255 fp->len = GETLONG(d.len);
258 else if(d.attr & 0x10){
259 fp->len = fat->clustsize * Sectsz;
270 conffat(Fat *fat, void *buf)
273 uint fatsize, volsize, datasize, reserved;
274 uint ver, dirsize, dirents, clusters;
276 if(GETSHORT(p->sectsize) != Sectsz)
278 if(memcmp(p->type, "FAT", 3) && memcmp(((Pbs32*)buf)->type, "FAT", 3))
281 /* load values from fat */
283 fatsize = GETSHORT(p->fatsize);
285 fatsize = GETLONG(((Pbs32*)buf)->fatsize);
288 volsize = GETSHORT(p->volsize);
290 volsize = GETLONG(p->bigvolsize);
291 reserved = GETSHORT(p->nreserv);
292 dirents = GETSHORT(p->rootsize);
293 dirsize = (dirents * Dirsz + Sectsz - 1) / Sectsz;
294 datasize = volsize - (reserved + fatsize * p->nfats + dirsize);
295 clusters = datasize / p->clustsize;
302 /* fill FAT descriptor */
304 fat->dirents = dirents;
305 fat->clustsize = p->clustsize;
306 fat->fatlba = fat->partlba + reserved;
307 fat->dirstart = fat->fatlba + fatsize * p->nfats;
309 fat->datalba = fat->dirstart;
310 fat->dirstart = GETLONG(((Pbs32*)buf)->rootclust);
311 fat->eofmark = 0xffffff7;
313 fat->datalba = fat->dirstart + dirsize;
315 fat->eofmark = 0xfff7;
317 fat->eofmark = 0xff7;
323 findfat(Fat *fat, int drive, ulong xbase, ulong lba)
338 if(readsect(drive, lba, buf))
340 if(buf[0x1fe] != 0x55 || buf[0x1ff] != 0xAA)
342 if(lba == 0 && (drive & 0x80) == 0){ /* floppy */
345 if(!conffat(fat, buf))
348 memmove(p, &buf[0x1be], sizeof(p));
354 /* extended partitions */
355 if(!findfat(fat, drive, xbase, xbase + GETLONG(p[i].lba)))
361 if(p[i].status != 0x80)
363 case 0x39: /* always try plan9 partition */
365 fat->partlba = lba + GETLONG(p[i].lba);
366 if(readsect(drive, fat->partlba, buf))
368 if(!conffat(fat, buf))
378 char path[Maxpath], *kern;
384 /* drive passed in DL */
385 drive = ((ushort*)sp)[5] & 0xFF;
387 if(findfat(&fat, drive, 0, 0)){
391 if(fatwalk(f = &fi, &fat, "plan9.ini")){
392 print("no config\n");
396 kern = configure(f, path); f = 0;
397 if(fatwalk(&fi, &fat, kern)){
398 print("not found\n");
401 print(bootkern(&fi));