00001 #include "devices/partition.h"
00002
00003 #include <packed.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <stdio.h>
00007 #include "devices/block.h"
00008 #include "threads/malloc.h"
00009
00010
00011 struct partition
00012 {
00013 struct block *block;
00014 block_sector_t start;
00015 };
00016
00017 static struct block_operations partition_operations;
00018
00019 static void read_partition_table (struct block *, block_sector_t sector,
00020 block_sector_t primary_extended_sector,
00021 int *part_nr);
00022 static void found_partition (struct block *, uint8_t type,
00023 block_sector_t start, block_sector_t size,
00024 int part_nr);
00025 static const char *partition_type_name (uint8_t);
00026
00027
00028 void
00029 partition_scan (struct block *block)
00030 {
00031 int part_nr = 0;
00032 read_partition_table (block, 0, 0, &part_nr);
00033 if (part_nr == 0)
00034 printf ("%s: Device contains no partitions\n", block_name (block));
00035 }
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 static void
00051 read_partition_table (struct block *block, block_sector_t sector,
00052 block_sector_t primary_extended_sector,
00053 int *part_nr)
00054 {
00055
00056 struct partition_table_entry
00057 {
00058 uint8_t bootable;
00059 uint8_t start_chs[3];
00060 uint8_t type;
00061 uint8_t end_chs[3];
00062 uint32_t offset;
00063 uint32_t size;
00064 }
00065 PACKED;
00066
00067
00068 struct partition_table
00069 {
00070 uint8_t loader[446];
00071 struct partition_table_entry partitions[4];
00072 uint16_t signature;
00073 }
00074 PACKED;
00075
00076 struct partition_table *pt;
00077 size_t i;
00078
00079
00080 if (sector >= block_size (block))
00081 {
00082 printf ("%s: Partition table at sector %"PRDSNu" past end of device.\n",
00083 block_name (block), sector);
00084 return;
00085 }
00086
00087
00088 ASSERT (sizeof *pt == BLOCK_SECTOR_SIZE);
00089 pt = malloc (sizeof *pt);
00090 if (pt == NULL)
00091 PANIC ("Failed to allocate memory for partition table.");
00092 block_read (block, 0, pt);
00093
00094
00095 if (pt->signature != 0xaa55)
00096 {
00097 if (primary_extended_sector == 0)
00098 printf ("%s: Invalid partition table signature\n", block_name (block));
00099 else
00100 printf ("%s: Invalid extended partition table in sector %"PRDSNu"\n",
00101 block_name (block), sector);
00102 free (pt);
00103 return;
00104 }
00105
00106
00107 for (i = 0; i < sizeof pt->partitions / sizeof *pt->partitions; i++)
00108 {
00109 struct partition_table_entry *e = &pt->partitions[i];
00110
00111 if (e->size == 0 || e->type == 0)
00112 {
00113
00114 }
00115 else if (e->type == 0x05
00116 || e->type == 0x0f
00117 || e->type == 0x85
00118 || e->type == 0xc5)
00119 {
00120 printf ("%s: Extended partition in sector %"PRDSNu"\n",
00121 block_name (block), sector);
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 if (sector == 0)
00132 read_partition_table (block, e->offset, e->offset, part_nr);
00133 else
00134 read_partition_table (block, e->offset + primary_extended_sector,
00135 primary_extended_sector, part_nr);
00136 }
00137 else
00138 {
00139 ++*part_nr;
00140
00141 found_partition (block, e->type, e->offset + sector,
00142 e->size, *part_nr);
00143 }
00144 }
00145
00146 free (pt);
00147 }
00148
00149
00150
00151
00152
00153
00154 static void
00155 found_partition (struct block *block, uint8_t part_type,
00156 block_sector_t start, block_sector_t size,
00157 int part_nr)
00158 {
00159 if (start >= block_size (block))
00160 printf ("%s%d: Partition starts past end of device (sector %"PRDSNu")\n",
00161 block_name (block), part_nr, start);
00162 else if (start + size < start || start + size > block_size (block))
00163 printf ("%s%d: Partition end (%"PRDSNu") past end of device (%"PRDSNu")\n",
00164 block_name (block), part_nr, start + size, block_size (block));
00165 else
00166 {
00167 enum block_type type = (part_type == 0x20 ? BLOCK_KERNEL
00168 : part_type == 0x21 ? BLOCK_FILESYS
00169 : part_type == 0x22 ? BLOCK_SCRATCH
00170 : part_type == 0x23 ? BLOCK_SWAP
00171 : BLOCK_FOREIGN);
00172 struct partition *p;
00173 char extra_info[128];
00174 char name[16];
00175
00176 p = malloc (sizeof *p);
00177 if (p == NULL)
00178 PANIC ("Failed to allocate memory for partition descriptor");
00179 p->block = block;
00180 p->start = start;
00181
00182 snprintf (name, sizeof name, "%s%d", block_name (block), part_nr);
00183 snprintf (extra_info, sizeof extra_info, "%s (%02x)",
00184 partition_type_name (part_type), part_type);
00185 block_register (name, type, extra_info, size, &partition_operations, p);
00186 }
00187 }
00188
00189
00190 static const char *
00191 partition_type_name (uint8_t type)
00192 {
00193
00194
00195
00196
00197 static const char *type_names[256] =
00198 {
00199 [0x00] = "Empty",
00200 [0x01] = "FAT12",
00201 [0x02] = "XENIX root",
00202 [0x03] = "XENIX usr",
00203 [0x04] = "FAT16 <32M",
00204 [0x05] = "Extended",
00205 [0x06] = "FAT16",
00206 [0x07] = "HPFS/NTFS",
00207 [0x08] = "AIX",
00208 [0x09] = "AIX bootable",
00209 [0x0a] = "OS/2 Boot Manager",
00210 [0x0b] = "W95 FAT32",
00211 [0x0c] = "W95 FAT32 (LBA)",
00212 [0x0e] = "W95 FAT16 (LBA)",
00213 [0x0f] = "W95 Ext'd (LBA)",
00214 [0x10] = "OPUS",
00215 [0x11] = "Hidden FAT12",
00216 [0x12] = "Compaq diagnostics",
00217 [0x14] = "Hidden FAT16 <32M",
00218 [0x16] = "Hidden FAT16",
00219 [0x17] = "Hidden HPFS/NTFS",
00220 [0x18] = "AST SmartSleep",
00221 [0x1b] = "Hidden W95 FAT32",
00222 [0x1c] = "Hidden W95 FAT32 (LBA)",
00223 [0x1e] = "Hidden W95 FAT16 (LBA)",
00224 [0x20] = "Pintos OS kernel",
00225 [0x21] = "Pintos file system",
00226 [0x22] = "Pintos scratch",
00227 [0x23] = "Pintos swap",
00228 [0x24] = "NEC DOS",
00229 [0x39] = "Plan 9",
00230 [0x3c] = "PartitionMagic recovery",
00231 [0x40] = "Venix 80286",
00232 [0x41] = "PPC PReP Boot",
00233 [0x42] = "SFS",
00234 [0x4d] = "QNX4.x",
00235 [0x4e] = "QNX4.x 2nd part",
00236 [0x4f] = "QNX4.x 3rd part",
00237 [0x50] = "OnTrack DM",
00238 [0x51] = "OnTrack DM6 Aux1",
00239 [0x52] = "CP/M",
00240 [0x53] = "OnTrack DM6 Aux3",
00241 [0x54] = "OnTrackDM6",
00242 [0x55] = "EZ-Drive",
00243 [0x56] = "Golden Bow",
00244 [0x5c] = "Priam Edisk",
00245 [0x61] = "SpeedStor",
00246 [0x63] = "GNU HURD or SysV",
00247 [0x64] = "Novell Netware 286",
00248 [0x65] = "Novell Netware 386",
00249 [0x70] = "DiskSecure Multi-Boot",
00250 [0x75] = "PC/IX",
00251 [0x80] = "Old Minix",
00252 [0x81] = "Minix / old Linux",
00253 [0x82] = "Linux swap / Solaris",
00254 [0x83] = "Linux",
00255 [0x84] = "OS/2 hidden C: drive",
00256 [0x85] = "Linux extended",
00257 [0x86] = "NTFS volume set",
00258 [0x87] = "NTFS volume set",
00259 [0x88] = "Linux plaintext",
00260 [0x8e] = "Linux LVM",
00261 [0x93] = "Amoeba",
00262 [0x94] = "Amoeba BBT",
00263 [0x9f] = "BSD/OS",
00264 [0xa0] = "IBM Thinkpad hibernation",
00265 [0xa5] = "FreeBSD",
00266 [0xa6] = "OpenBSD",
00267 [0xa7] = "NeXTSTEP",
00268 [0xa8] = "Darwin UFS",
00269 [0xa9] = "NetBSD",
00270 [0xab] = "Darwin boot",
00271 [0xb7] = "BSDI fs",
00272 [0xb8] = "BSDI swap",
00273 [0xbb] = "Boot Wizard hidden",
00274 [0xbe] = "Solaris boot",
00275 [0xbf] = "Solaris",
00276 [0xc1] = "DRDOS/sec (FAT-12)",
00277 [0xc4] = "DRDOS/sec (FAT-16 < 32M)",
00278 [0xc6] = "DRDOS/sec (FAT-16)",
00279 [0xc7] = "Syrinx",
00280 [0xda] = "Non-FS data",
00281 [0xdb] = "CP/M / CTOS / ...",
00282 [0xde] = "Dell Utility",
00283 [0xdf] = "BootIt",
00284 [0xe1] = "DOS access",
00285 [0xe3] = "DOS R/O",
00286 [0xe4] = "SpeedStor",
00287 [0xeb] = "BeOS fs",
00288 [0xee] = "EFI GPT",
00289 [0xef] = "EFI (FAT-12/16/32)",
00290 [0xf0] = "Linux/PA-RISC boot",
00291 [0xf1] = "SpeedStor",
00292 [0xf4] = "SpeedStor",
00293 [0xf2] = "DOS secondary",
00294 [0xfd] = "Linux raid autodetect",
00295 [0xfe] = "LANstep",
00296 [0xff] = "BBT",
00297 };
00298
00299 return type_names[type] != NULL ? type_names[type] : "Unknown";
00300 }
00301
00302
00303
00304 static void
00305 partition_read (void *p_, block_sector_t sector, void *buffer)
00306 {
00307 struct partition *p = p_;
00308 block_read (p->block, p->start + sector, buffer);
00309 }
00310
00311
00312
00313
00314 static void
00315 partition_write (void *p_, block_sector_t sector, const void *buffer)
00316 {
00317 struct partition *p = p_;
00318 block_write (p->block, p->start + sector, buffer);
00319 }
00320
00321 static struct block_operations partition_operations =
00322 {
00323 partition_read,
00324 partition_write
00325 };