static bool_t dos_partition(struct disk * disk, size_t sector, size_t relative) { struct dos_partition_mbr mbr; struct partition * part; size_t start; int i; if(!disk || !disk->name) return FALSE; if((disk->sector_size <= 0) || (disk->sector_count <=0)) return FALSE; if((!disk->read_sectors) || (!disk->write_sectors)) return FALSE; if(disk_read(disk, (u8_t *)(&mbr), (loff_t)(sector * disk->sector_size) , sizeof(struct dos_partition_mbr)) != sizeof(struct dos_partition_mbr)) return FALSE; /* * check dos partition's signature */ if((mbr.signature[0] != 0x55) || mbr.signature[1] != 0xaa) return FALSE; for(i=0; i<4; i++) { if((mbr.entry[i].type != 0) && (is_dos_extended(mbr.entry[i].type)==FALSE)) { part = malloc(sizeof(struct partition)); if(!part) return FALSE; strlcpy((char *)part->name, (const char *)"", sizeof(part->name)); part->sector_from = sector + ((mbr.entry[i].start[3] << 24) | (mbr.entry[i].start[2] << 16) | (mbr.entry[i].start[1] << 8) | (mbr.entry[i].start[0] << 0)); part->sector_to = part->sector_from + ((mbr.entry[i].length[3] << 24) | (mbr.entry[i].length[2] << 16) | (mbr.entry[i].length[1] << 8) | (mbr.entry[i].length[0] << 0)) - 1; part->sector_size = disk->sector_size; list_add_tail(&part->entry, &(disk->info.entry)); } } for(i=0; i<4; i++) { if(is_dos_extended(mbr.entry[i].type)==TRUE) { start = ((mbr.entry[i].start[3] << 24) | (mbr.entry[i].start[2] << 16) | (mbr.entry[i].start[1] << 8) | (mbr.entry[i].start[0] << 0)) + relative; return dos_partition(disk, start, (sector == 0) ? start : relative); } } return TRUE; }
Retcode dos_partition(Environ *e, Filesys_action what, Instance *disk, Byte *path, uLong loc, uLong start_unused, uByte *buf, uInt size, uByte *retbuf, uLong *val) { int i, j; Retcode ret = NO_ERROR; int partition = -1; struct bootsector50 *bs = (struct bootsector50*)buf; struct dos_partition part[NDOSPART]; static int indent = 0; DPRINTF(("\ndos_partition: enter\n")); if (size < DOS_BLOCK_SIZE) return E_BLOCKSIZE; /* first see if this is a DOS boot-block */ ret = filesys_read_bytes(e, disk, loc, size, buf); if (ret != NO_ERROR) return ret; DPRINTF(("dos-partition: boot_sect_sig0/1=%#x.%#x jump=%#x" " boot_signature=%#x drive_number=%#x\n", bs->boot_sect_sig[0], bs->boot_sect_sig[1], bs->jump[0], bs->boot_signature, bs->drive_number)); if (bs->boot_sect_sig[0] != BOOTSIG0 || bs->boot_sect_sig[1] != BOOTSIG1 || ((bs->jump[0] == 0xE9 || bs->jump[0] == 0xEB) && bs->boot_signature != 0x29 && bs->boot_signature != 0x13 && bs->boot_signature != 0x7C && bs->boot_signature != 0xBC)) return E_NO_FILESYS; /* copy the partition info */ memcpy((void*)part, buf + DOSPARTOFF, sizeof part); /* see if we have any partitions - may not be a partition table */ for (i = 0; i < 4; i++) { if (part[i].typ != DP_UNUSED) break; } if (i >= 4) return E_NO_FILESYS; if (*path >= '0' && *path <= '3') { partition = *path - '0'; path = strchr(path, ','); if (path == NULL) path = ""; else path++; } else if (*path) { cprintf(e, "dos-partition: unknown partition %s\n", path); return E_ABORT; } if (what == FS_PROBE) strcat((char*)retbuf, ",dos-partition"); for (i = 0; i < 4; i++) { struct dos_partition *p = &part[i]; uInt start, size; /* handle alignment and endian problems */ start = p->start[0] | (p->start[1] << BYTE_SIZE) | (p->start[2] << BYTE_SIZE * 2) | (p->start[3] << BYTE_SIZE * 3); size = p->size[0] | (p->size[1] << BYTE_SIZE) | (p->size[2] << BYTE_SIZE * 2) | (p->size[3] << BYTE_SIZE * 3); DPRINTF(("dos_partition: partition=%d size=%#x start=%#x typ=%#x\n" "\tflag=%#x shd=%#x ssect=%#x scyl=%#x ehd=%#x" " esect=%#x ecyl=%#x\n", i, size, start, p->typ, p->flag, p->shd, p->ssect, p->scyl, p->ehd, p->esect, p->ecyl)); /* find matching fstype */ if (what == FS_LIST && partition < 0) { DPtype *fs; for (fs = g_dplist; fs->name; fs++) if (fs->type == p->typ) break; for (j = 0; j < indent; j++) cprintf(e, " "); cprintf(e, "DOS partition %d: %s (%#x)\n", i, fs->name ? fs->name : "<unknown>", p->typ); } /* make sure we have something in this partition */ if (size == 0 || p->typ == DP_UNUSED) { if (i == partition && what != FS_PROBE) return E_NO_FILESYS; continue; } if (p->typ == DP_EXTENDED) { indent += 4; ret = dos_partition(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); indent -= 4; if (ret != NO_ERROR && ret != E_NO_FILESYS && ret != R_END) return ret; continue; } /* handle filesystems inside our partitions */ switch (what) { case FS_PROBE: ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); if (ret != NO_ERROR && ret != E_NO_FILESYS) return ret; break; case FS_LIST: if (i == partition) { ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); return (ret == E_NO_FILESYS) ? E_UNSUPPORTED_FILESYS : ret; } break; case FS_LOAD: if (i == partition) { if (*path) { ret = file_system(e, what, disk, path, loc + start * DOS_BLOCK_SIZE, start, buf, DOS_BLOCK_SIZE, retbuf, val); return (ret == E_NO_FILESYS) ? E_UNSUPPORTED_FILESYS : ret; } /* no path specified - try to load this partition's bootblock */ return filesys_read_bytes(e, disk, loc + start * DOS_BLOCK_SIZE, *val = DOS_BLOCK_SIZE, retbuf); } else if (i < 0) /* no partition specified - try to load MBR */ return filesys_read_bytes(e, disk, loc * DOS_BLOCK_SIZE, *val = DOS_BLOCK_SIZE, retbuf); break; } } /* no other partitions or filesystems should be on this volume */ DPRINTF(("dos_partition: return R_END\n")); return R_END; }
static bool_t parser_probe_dos(struct disk * disk) { return dos_partition(disk, 0, 0); }
int fatfindfile(char *fname) { int rc, i, j; putstr("--MBR--\n"); rc = readblock(DOSBBSECTOR, buf); if (dos_partition(0)->dp_typ != 6) { putstr("bad partition type\n"); return -1; }; start = getulong(dos_partition(0)->dp_start); dump_long("start ", start); putstr("--BOOT--\n"); rc = readblock(start, buf); if (getushort(bootsector->bpbBytesPerSec) != 512) { putstr("bad sector size\n"); return -1; }; cluster_size = bootsector->bpbSecPerClust; dump_long("cluster_size ", cluster_size); start_fat = start + getushort(bootsector->bpbResSectors); dump_long("start_fat ", start_fat); root_size = getushort(bootsector->bpbRootDirEnts); root_size = (root_size * 32+511)/512; dump_long("root_size ", root_size); dump_long("FATsecs ", getushort(bootsector->bpbFATsecs)); dump_long("FATs ", bootsector->bpbFATs); start_root = start_fat + bootsector->bpbFATs * getushort(bootsector->bpbFATsecs); start = start_root + root_size - 2 * cluster_size; /* first data sector for 0-based clusters */ dump_long("start_root ", start_root); current_cluster = 0; putstr("--ROOT--\n"); for(j = 0; j<root_size; j++) { rc = readblock(start_root + j, buf); for(i = 0; i<16; i++) { rc = (direntry(i)->deName)[0]; if (rc == SLOT_EMPTY || rc == SLOT_DELETED) continue; rc = direntry(i)->deAttributes & (ATTR_VOLUME|ATTR_DIRECTORY); if (rc) continue; current_cluster = getushort(direntry(i)->deStartCluster); bytes_left = getulong(direntry(i)->deFileSize); putstr(direntry(i)->deName); putnl(); /* printf("%12s %02x %ld %ld\n", direntry(i)->deName, direntry(i)->deAttributes & 0x18, current_cluster, bytes_left ); */ if (!strncmp(direntry(i)->deName, fname, 11)) { break; }; current_cluster = 0; }; if (current_cluster) break; }; if (!current_cluster) { putstr("file not found\n"); return -1; }; current_sector = 0; putstr("File ok\n"); return 0; }