Changeset 0712ff2 in mainline
- Timestamp:
- 2009-09-01T21:33:16Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- e86a849a
- Parents:
- cd3e6a2 (diff), e27b89a (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/part/mbr_part/mbr_part.c
rcd3e6a2 r0712ff2 38 38 * and provides one for each partition. 39 39 * 40 * Limitations: 41 * 40 42 * Only works with boot records using LBA. CHS-only records are not 41 * supported. Only primary partition records are supported.43 * supported. Maximum number of partitions is fixed. 42 44 */ 43 45 44 46 #include <stdio.h> 47 #include <stdlib.h> 45 48 #include <unistd.h> 46 49 #include <ipc/ipc.h> … … 56 59 #include <bool.h> 57 60 #include <byteorder.h> 61 #include <assert.h> 58 62 #include <macros.h> 59 63 #include <task.h> … … 66 70 67 71 /** Boot record signature */ 68 BR_SIGNATURE = 0xAA55 72 BR_SIGNATURE = 0xAA55, 69 73 }; 70 74 75 enum ptype { 76 /** Extended partition */ 77 PT_EXTENDED = 0x05 78 }; 79 71 80 /** Partition */ 72 typedef struct {81 typedef struct part { 73 82 /** Primary partition entry is in use */ 74 83 bool present; … … 79 88 /** Device representing the partition (outbound device) */ 80 89 dev_handle_t dev; 90 /** Points to next partition structure. */ 91 struct part *next; 81 92 } part_t; 82 93 … … 86 97 /** CHS of fist block in partition */ 87 98 uint8_t first_chs[3]; 99 /** Partition type */ 100 uint8_t ptype; 88 101 /** CHS of last block in partition */ 89 102 uint8_t last_chs[3]; 90 /** Partition type */91 uint8_t ptype;92 103 /** LBA of first block in partition */ 93 104 uint32_t first_lba; … … 119 130 static dev_handle_t indev_handle; 120 131 121 static part_t primary[N_PRIMARY]; 132 /** List of partitions. This structure is an empty head. */ 133 static part_t plist_head; 122 134 123 135 static int mbr_init(const char *dev_name); 124 136 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); 125 139 static void mbr_connection(ipc_callid_t iid, ipc_call_t *icall); 126 140 static int mbr_bd_read(part_t *p, uint64_t ba, size_t cnt, void *buf); … … 128 142 static int mbr_bsa_translate(part_t *p, uint64_t ba, size_t cnt, uint64_t *gba); 129 143 130 131 144 int main(int argc, char **argv) 132 145 { 133 146 printf(NAME ": PC MBR partition driver\n"); 134 printf(NAME ": Size of br_block_t = %d\n", sizeof(br_block_t));135 147 136 148 if (argc != 2) { … … 157 169 dev_handle_t dev; 158 170 uint64_t size_mb; 171 part_t *part; 159 172 160 173 rc = devmap_device_get_handle(dev_name, &indev_handle, 0); … … 195 208 } 196 209 197 /* Create partition devices. */ 198 for (i = 0; i < N_PRIMARY; ++i) { 210 /* 211 * Create partition devices. 212 */ 213 i = 0; 214 part = plist_head.next; 215 216 while (part != NULL) { 199 217 /* Skip absent partitions. */ 200 if (!primary[i].present) 218 if (!part->present) { 219 part = part->next; 220 ++i; 201 221 continue; 222 } 202 223 203 224 asprintf(&name, "%sp%d", dev_name, i); 225 if (name == NULL) 226 return ENOMEM; 227 204 228 rc = devmap_device_register(name, &dev); 205 229 if (rc != EOK) { … … 209 233 } 210 234 211 size_mb = (p rimary[i].length * block_size + 1024 * 1024 - 1)235 size_mb = (part->length * block_size + 1024 * 1024 - 1) 212 236 / (1024 * 1024); 213 237 printf(NAME ": Registered device %s: %llu blocks %llu MB.\n", 214 name, primary[i].length, size_mb); 215 216 primary[i].dev = dev; 238 name, part->length, size_mb); 239 240 part->dev = dev; 241 free(name); 242 243 part = part->next; 244 ++i; 217 245 } 218 246 … … 224 252 { 225 253 int i, rc; 226 br_block_t * mbr;254 br_block_t *brb; 227 255 uint16_t sgn; 228 uint32_t sa, len; 229 230 rc = block_bb_read(indev_handle, 0); 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); 231 272 if (rc != EOK) { 232 273 printf(NAME ": Failed reading MBR block.\n"); … … 234 275 } 235 276 236 mbr = block_bb_get(indev_handle); 237 sgn = uint16_t_le2host(mbr->signature); 238 277 sgn = uint16_t_le2host(brb->signature); 239 278 if (sgn != BR_SIGNATURE) { 240 279 printf(NAME ": Invalid boot record signature 0x%04X.\n", sgn); … … 242 281 } 243 282 283 ext_part = NULL; 284 plist_head.next = NULL; 285 prev = &plist_head; 286 244 287 for (i = 0; i < N_PRIMARY; ++i) { 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 } 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; 254 370 } 255 371 … … 266 382 uint64_t ba; 267 383 size_t cnt; 268 int pidx, i;269 384 part_t *part; 270 385 … … 272 387 dh = IPC_GET_ARG1(*icall); 273 388 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*/) { 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) { 281 399 ipc_answer_0(iid, EINVAL); 282 400 return; 283 401 } 284 402 285 part = &primary[pidx];403 assert(part->present == true); 286 404 287 405 /* Answer the IPC_M_CONNECT_ME_TO call. */
Note:
See TracChangeset
for help on using the changeset viewer.