Changes in / [0712ff2:cd3e6a2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/part/mbr_part/mbr_part.c
r0712ff2 rcd3e6a2 38 38 * and provides one for each partition. 39 39 * 40 * Limitations:41 *42 40 * Only works with boot records using LBA. CHS-only records are not 43 * supported. Maximum number of partitions is fixed.41 * supported. Only primary partition records are supported. 44 42 */ 45 43 46 44 #include <stdio.h> 47 #include <stdlib.h>48 45 #include <unistd.h> 49 46 #include <ipc/ipc.h> … … 59 56 #include <bool.h> 60 57 #include <byteorder.h> 61 #include <assert.h>62 58 #include <macros.h> 63 59 #include <task.h> … … 70 66 71 67 /** Boot record signature */ 72 BR_SIGNATURE = 0xAA55 ,68 BR_SIGNATURE = 0xAA55 73 69 }; 74 70 75 enum ptype {76 /** Extended partition */77 PT_EXTENDED = 0x0578 };79 80 71 /** Partition */ 81 typedef struct part{72 typedef struct { 82 73 /** Primary partition entry is in use */ 83 74 bool present; … … 88 79 /** Device representing the partition (outbound device) */ 89 80 dev_handle_t dev; 90 /** Points to next partition structure. */91 struct part *next;92 81 } part_t; 93 82 … … 97 86 /** CHS of fist block in partition */ 98 87 uint8_t first_chs[3]; 88 /** CHS of last block in partition */ 89 uint8_t last_chs[3]; 99 90 /** Partition type */ 100 91 uint8_t ptype; 101 /** CHS of last block in partition */102 uint8_t last_chs[3];103 92 /** LBA of first block in partition */ 104 93 uint32_t first_lba; … … 130 119 static dev_handle_t indev_handle; 131 120 132 /** List of partitions. This structure is an empty head. */ 133 static part_t plist_head; 121 static part_t primary[N_PRIMARY]; 134 122 135 123 static int mbr_init(const char *dev_name); 136 124 static int mbr_part_read(void); 137 static part_t *mbr_part_new(void);138 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part);139 125 static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall); 140 126 static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf); … … 142 128 static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba); 143 129 130 144 131 int main(int argc, char **argv) 145 132 { 146 133 printf(NAME ": PC MBR partition driver\n"); 134 printf(NAME ": Size of br_block_t = %d\n", sizeof(br_block_t)); 147 135 148 136 if (argc != 2) { … … 169 157 dev_handle_t dev; 170 158 uint64_t size_mb; 171 part_t *part;172 159 173 160 rc = devmap_device_get_handle(dev_name, &indev_handle, 0); … … 208 195 } 209 196 210 /* 211 * Create partition devices. 212 */ 213 i = 0; 214 part = plist_head.next; 215 216 while (part != NULL) { 197 /* Create partition devices. */ 198 for (i = 0; i < N_PRIMARY; ++i) { 217 199 /* Skip absent partitions. */ 218 if (!part->present) { 219 part = part->next; 220 ++i; 200 if (!primary[i].present) 221 201 continue; 222 }223 202 224 203 asprintf(&name, "%sp%d", dev_name, i); 225 if (name == NULL)226 return ENOMEM;227 228 204 rc = devmap_device_register(name, &dev); 229 205 if (rc != EOK) { … … 233 209 } 234 210 235 size_mb = (p art->length * block_size + 1024 * 1024 - 1)211 size_mb = (primary[i].length * block_size + 1024 * 1024 - 1) 236 212 / (1024 * 1024); 237 213 printf(NAME ": Registered device %s: %llu blocks %llu MB.\n", 238 name, part->length, size_mb); 239 240 part->dev = dev; 241 free(name); 242 243 part = part->next; 244 ++i; 214 name, primary[i].length, size_mb); 215 216 primary[i].dev = dev; 245 217 } 246 218 … … 252 224 { 253 225 int i, rc; 254 br_block_t * brb;226 br_block_t *mbr; 255 227 uint16_t sgn; 256 uint32_t ba; 257 part_t *ext_part, cp; 258 uint32_t base; 259 part_t *prev, *p; 260 261 brb = malloc(sizeof(br_block_t)); 262 if (brb == NULL) { 263 printf(NAME ": Failed allocating memory.\n"); 264 return ENOMEM; 265 } 266 267 /* 268 * Read primary partition entries. 269 */ 270 271 rc = block_read_direct(indev_handle, 0, 1, brb); 228 uint32_t sa, len; 229 230 rc = block_bb_read(indev_handle, 0); 272 231 if (rc != EOK) { 273 232 printf(NAME ": Failed reading MBR block.\n"); … … 275 234 } 276 235 277 sgn = uint16_t_le2host(brb->signature); 236 mbr = block_bb_get(indev_handle); 237 sgn = uint16_t_le2host(mbr->signature); 238 278 239 if (sgn != BR_SIGNATURE) { 279 240 printf(NAME ": Invalid boot record signature 0x%04X.\n", sgn); … … 281 242 } 282 243 283 ext_part = NULL;284 plist_head.next = NULL;285 prev = &plist_head;286 287 244 for (i = 0; i < N_PRIMARY; ++i) { 288 p = mbr_part_new(); 289 if (p == NULL) 290 return ENOMEM; 291 292 mbr_pte_to_part(0, &brb->pte[i], p); 293 prev->next = p; 294 prev = p; 295 296 if (brb->pte[i].ptype == PT_EXTENDED) { 297 p->present = false; 298 ext_part = p; 299 } 300 } 301 302 if (ext_part == NULL) 303 return EOK; 304 305 printf("Extended partition found.\n"); 306 307 /* 308 * Read extended partition entries. 309 */ 310 311 cp.start_addr = ext_part->start_addr; 312 cp.length = ext_part->length; 313 base = ext_part->start_addr; 314 315 do { 316 /* 317 * Addressing in the EBR chain is relative to the beginning 318 * of the extended partition. 319 */ 320 ba = cp.start_addr; 321 rc = block_read_direct(indev_handle, ba, 1, brb); 322 if (rc != EOK) { 323 printf(NAME ": Failed reading EBR block at %u.\n", ba); 324 return rc; 325 } 326 327 sgn = uint16_t_le2host(brb->signature); 328 if (sgn != BR_SIGNATURE) { 329 printf(NAME ": Invalid boot record signature 0x%04X " 330 " in EBR at %u.\n", sgn, ba); 331 return EINVAL; 332 } 333 334 p = mbr_part_new(); 335 if (p == NULL) 336 return ENOMEM; 337 338 /* First PTE is the logical partition itself. */ 339 mbr_pte_to_part(base, &brb->pte[0], p); 340 prev->next = p; 341 prev = p; 342 343 /* Second PTE describes next chain element. */ 344 mbr_pte_to_part(base, &brb->pte[1], &cp); 345 } while (cp.present); 346 347 return EOK; 348 } 349 350 /** Allocate a new @c part_t structure. */ 351 static part_t *mbr_part_new(void) 352 { 353 return malloc(sizeof(part_t)); 354 } 355 356 /** Parse partition table entry. */ 357 static void mbr_pte_to_part(uint32_t base, const pt_entry_t *pte, part_t *part) 358 { 359 uint32_t sa, len; 360 361 sa = uint32_t_le2host(pte->first_lba); 362 len = uint32_t_le2host(pte->length); 363 364 part->start_addr = base + sa; 365 part->length = len; 366 367 part->present = (sa != 0 || len != 0) ? true : false; 368 part->dev = 0; 369 part->next = NULL; 245 sa = uint32_t_le2host(mbr->pte[i].first_lba); 246 len = uint32_t_le2host(mbr->pte[i].length); 247 248 primary[i].start_addr = sa; 249 primary[i].length = len; 250 251 primary[i].present = (sa != 0 || len != 0) ? true : false; 252 primary[i].dev = 0; 253 } 370 254 } 371 255 … … 382 266 uint64_t ba; 383 267 size_t cnt; 268 int pidx, i; 384 269 part_t *part; 385 270 … … 387 272 dh = IPC_GET_ARG1(*icall); 388 273 389 /* 390 * Determine which partition device is the client connecting to. 391 * A linear search is not terribly fast, but we only do this 392 * once for each connection. 393 */ 394 part = plist_head.next; 395 while (part != NULL && part->dev != dh) 396 part = part->next; 397 398 if (part == NULL) { 274 /* Determine which partition device is the client connecting to. */ 275 pidx = -1; 276 for (i = 0; i < N_PRIMARY; i++) 277 if (primary[i].dev == dh) 278 pidx = i; 279 280 if (pidx < 0/* || disk[disk_id].present == false*/) { 399 281 ipc_answer_0(iid, EINVAL); 400 282 return; 401 283 } 402 284 403 assert(part->present == true);285 part = &primary[pidx]; 404 286 405 287 /* Answer the IPC_M_CONNECT_ME_TO call. */
Note:
See TracChangeset
for help on using the changeset viewer.