1 /*- 2 * Copyright (c) 2010 Marcel Moolenaar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/disk.h> 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/queue.h> 34 #include <stddef.h> 35 #include <stdarg.h> 36 37 #include <bootstrap.h> 38 39 #include <efi.h> 40 #include <efilib.h> 41 #include <efiprot.h> 42 #include <efichar.h> 43 #include <disk.h> 44 45 static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; 46 47 typedef bool (*pd_test_cb_t)(pdinfo_t *, pdinfo_t *); 48 static int efipart_initfd(void); 49 static int efipart_initcd(void); 50 static int efipart_inithd(void); 51 static void efipart_cdinfo_add(pdinfo_t *); 52 53 static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *); 54 static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *); 55 56 static int efipart_open(struct open_file *, ...); 57 static int efipart_close(struct open_file *); 58 static int efipart_ioctl(struct open_file *, u_long, void *); 59 60 static int efipart_printfd(int); 61 static int efipart_printcd(int); 62 static int efipart_printhd(int); 63 64 /* EISA PNP ID's for floppy controllers */ 65 #define PNP0604 0x604 66 #define PNP0700 0x700 67 #define PNP0701 0x701 68 69 /* Bounce buffer max size */ 70 #define BIO_BUFFER_SIZE 0x4000 71 72 struct devsw efipart_fddev = { 73 .dv_name = "fd", 74 .dv_type = DEVT_FD, 75 .dv_init = efipart_initfd, 76 .dv_strategy = efipart_strategy, 77 .dv_open = efipart_open, 78 .dv_close = efipart_close, 79 .dv_ioctl = efipart_ioctl, 80 .dv_print = efipart_printfd, 81 .dv_cleanup = NULL 82 }; 83 84 struct devsw efipart_cddev = { 85 .dv_name = "cd", 86 .dv_type = DEVT_CD, 87 .dv_init = efipart_initcd, 88 .dv_strategy = efipart_strategy, 89 .dv_open = efipart_open, 90 .dv_close = efipart_close, 91 .dv_ioctl = efipart_ioctl, 92 .dv_print = efipart_printcd, 93 .dv_cleanup = NULL 94 }; 95 96 struct devsw efipart_hddev = { 97 .dv_name = "disk", 98 .dv_type = DEVT_DISK, 99 .dv_init = efipart_inithd, 100 .dv_strategy = efipart_strategy, 101 .dv_open = efipart_open, 102 .dv_close = efipart_close, 103 .dv_ioctl = efipart_ioctl, 104 .dv_print = efipart_printhd, 105 .dv_cleanup = NULL 106 }; 107 108 static pdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo); 109 static pdinfo_list_t cdinfo = STAILQ_HEAD_INITIALIZER(cdinfo); 110 static pdinfo_list_t hdinfo = STAILQ_HEAD_INITIALIZER(hdinfo); 111 112 /* 113 * efipart_inithandles() is used to build up the pdinfo list from 114 * block device handles. Then each devsw init callback is used to 115 * pick items from pdinfo and move to proper device list. 116 * In ideal world, we should end up with empty pdinfo once all 117 * devsw initializers are called. 118 */ 119 static pdinfo_list_t pdinfo = STAILQ_HEAD_INITIALIZER(pdinfo); 120 121 pdinfo_list_t * 122 efiblk_get_pdinfo_list(struct devsw *dev) 123 { 124 if (dev->dv_type == DEVT_DISK) 125 return (&hdinfo); 126 if (dev->dv_type == DEVT_CD) 127 return (&cdinfo); 128 if (dev->dv_type == DEVT_FD) 129 return (&fdinfo); 130 return (NULL); 131 } 132 133 /* XXX this gets called way way too often, investigate */ 134 pdinfo_t * 135 efiblk_get_pdinfo(struct devdesc *dev) 136 { 137 pdinfo_list_t *pdi; 138 pdinfo_t *pd = NULL; 139 140 pdi = efiblk_get_pdinfo_list(dev->d_dev); 141 if (pdi == NULL) 142 return (pd); 143 144 STAILQ_FOREACH(pd, pdi, pd_link) { 145 if (pd->pd_unit == dev->d_unit) 146 return (pd); 147 } 148 return (pd); 149 } 150 151 pdinfo_t * 152 efiblk_get_pdinfo_by_device_path(EFI_DEVICE_PATH *path) 153 { 154 EFI_HANDLE h; 155 EFI_STATUS status; 156 EFI_DEVICE_PATH *devp = path; 157 158 status = BS->LocateDevicePath(&blkio_guid, &devp, &h); 159 if (EFI_ERROR(status)) 160 return (NULL); 161 return (efiblk_get_pdinfo_by_handle(h)); 162 } 163 164 static bool 165 same_handle(pdinfo_t *pd, EFI_HANDLE h) 166 { 167 168 return (pd->pd_handle == h || pd->pd_alias == h); 169 } 170 171 pdinfo_t * 172 efiblk_get_pdinfo_by_handle(EFI_HANDLE h) 173 { 174 pdinfo_t *dp, *pp; 175 176 /* 177 * Check hard disks, then cd, then floppy 178 */ 179 STAILQ_FOREACH(dp, &hdinfo, pd_link) { 180 if (same_handle(dp, h)) 181 return (dp); 182 STAILQ_FOREACH(pp, &dp->pd_part, pd_link) { 183 if (same_handle(pp, h)) 184 return (pp); 185 } 186 } 187 STAILQ_FOREACH(dp, &cdinfo, pd_link) { 188 if (same_handle(dp, h)) 189 return (dp); 190 STAILQ_FOREACH(pp, &dp->pd_part, pd_link) { 191 if (same_handle(pp, h)) 192 return (pp); 193 } 194 } 195 STAILQ_FOREACH(dp, &fdinfo, pd_link) { 196 if (same_handle(dp, h)) 197 return (dp); 198 } 199 return (NULL); 200 } 201 202 static int 203 efiblk_pdinfo_count(pdinfo_list_t *pdi) 204 { 205 pdinfo_t *pd; 206 int i = 0; 207 208 STAILQ_FOREACH(pd, pdi, pd_link) { 209 i++; 210 } 211 return (i); 212 } 213 214 static pdinfo_t * 215 efipart_find_parent(pdinfo_list_t *pdi, EFI_DEVICE_PATH *devpath) 216 { 217 pdinfo_t *pd; 218 EFI_DEVICE_PATH *parent; 219 220 /* We want to find direct parent */ 221 parent = efi_devpath_trim(devpath); 222 /* We should not get out of memory here but be careful. */ 223 if (parent == NULL) 224 return (NULL); 225 226 STAILQ_FOREACH(pd, pdi, pd_link) { 227 /* We must have exact match. */ 228 if (efi_devpath_match(pd->pd_devpath, parent)) 229 break; 230 } 231 free(parent); 232 return (pd); 233 } 234 235 /* 236 * Return true when we should ignore this device. 237 */ 238 static bool 239 efipart_ignore_device(EFI_HANDLE h, EFI_BLOCK_IO *blkio, 240 EFI_DEVICE_PATH *devpath) 241 { 242 EFI_DEVICE_PATH *node, *parent; 243 244 /* 245 * We assume the block size 512 or greater power of 2. 246 * Also skip devices with block size > 64k (16 is max 247 * ashift supported by zfs). 248 * iPXE is known to insert stub BLOCK IO device with 249 * BlockSize 1. 250 */ 251 if (blkio->Media->BlockSize < 512 || 252 blkio->Media->BlockSize > (1 << 16) || 253 !powerof2(blkio->Media->BlockSize)) { 254 efi_close_devpath(h); 255 return (true); 256 } 257 258 /* Allowed values are 0, 1 and power of 2. */ 259 if (blkio->Media->IoAlign > 1 && 260 !powerof2(blkio->Media->IoAlign)) { 261 efi_close_devpath(h); 262 return (true); 263 } 264 265 /* 266 * With device tree setup: 267 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0) 268 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x1) 269 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x2) 270 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3) 271 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3)/CDROM.. 272 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x3)/CDROM.. 273 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x4) 274 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x5) 275 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x6) 276 * PciRoot(0x0)/Pci(0x14,0x0)/USB(0x5,0)/USB(0x2,0x0)/Unit(0x7) 277 * 278 * In above exmple only Unit(0x3) has media, all other nodes are 279 * missing media and should not be used. 280 * 281 * No media does not always mean there is no device, but in above 282 * case, we can not really assume there is any device. 283 * Therefore, if this node is USB, or this node is Unit (LUN) and 284 * direct parent is USB and we have no media, we will ignore this 285 * device. 286 * 287 * Variation of the same situation, but with SCSI devices: 288 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x1) 289 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x2) 290 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x3) 291 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x3)/CD.. 292 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x3)/CD.. 293 * PciRoot(0x0)/Pci(0x1a,0x0)/USB(0x1,0)/USB(0x3,0x0)/SCSI(0x0,0x4) 294 * 295 * Here above the SCSI luns 1,2 and 4 have no media. 296 */ 297 298 /* Do not ignore device with media. */ 299 if (blkio->Media->MediaPresent) 300 return (false); 301 302 node = efi_devpath_last_node(devpath); 303 if (node == NULL) 304 return (false); 305 306 /* USB without media present */ 307 if (DevicePathType(node) == MESSAGING_DEVICE_PATH && 308 DevicePathSubType(node) == MSG_USB_DP) { 309 efi_close_devpath(h); 310 return (true); 311 } 312 313 parent = efi_devpath_trim(devpath); 314 if (parent != NULL) { 315 bool parent_is_usb = false; 316 317 node = efi_devpath_last_node(parent); 318 if (node == NULL) { 319 free(parent); 320 return (false); 321 } 322 if (DevicePathType(node) == MESSAGING_DEVICE_PATH && 323 DevicePathSubType(node) == MSG_USB_DP) 324 parent_is_usb = true; 325 free(parent); 326 327 node = efi_devpath_last_node(devpath); 328 if (node == NULL) 329 return (false); 330 if (parent_is_usb && 331 DevicePathType(node) == MESSAGING_DEVICE_PATH) { 332 /* 333 * no media, parent is USB and devicepath is 334 * LUN or SCSI. 335 */ 336 if (DevicePathSubType(node) == 337 MSG_DEVICE_LOGICAL_UNIT_DP || 338 DevicePathSubType(node) == MSG_SCSI_DP) { 339 efi_close_devpath(h); 340 return (true); 341 } 342 } 343 } 344 return (false); 345 } 346 347 int 348 efipart_inithandles(void) 349 { 350 unsigned i, nin; 351 UINTN sz; 352 EFI_HANDLE *hin; 353 EFI_DEVICE_PATH *devpath; 354 EFI_BLOCK_IO *blkio; 355 EFI_STATUS status; 356 pdinfo_t *pd; 357 358 if (!STAILQ_EMPTY(&pdinfo)) 359 return (0); 360 361 sz = 0; 362 hin = NULL; 363 status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, hin); 364 if (status == EFI_BUFFER_TOO_SMALL) { 365 hin = malloc(sz); 366 status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 367 hin); 368 if (EFI_ERROR(status)) 369 free(hin); 370 } 371 if (EFI_ERROR(status)) 372 return (efi_status_to_errno(status)); 373 374 nin = sz / sizeof(*hin); 375 #ifdef EFIPART_DEBUG 376 printf("%s: Got %d BLOCK IO MEDIA handle(s)\n", __func__, nin); 377 #endif 378 379 for (i = 0; i < nin; i++) { 380 /* 381 * Get devpath and open protocol. 382 * We should not get errors here 383 */ 384 if ((devpath = efi_lookup_devpath(hin[i])) == NULL) 385 continue; 386 387 status = OpenProtocolByHandle(hin[i], &blkio_guid, 388 (void **)&blkio); 389 if (EFI_ERROR(status)) { 390 printf("error %lu\n", EFI_ERROR_CODE(status)); 391 continue; 392 } 393 394 if (efipart_ignore_device(hin[i], blkio, devpath)) 395 continue; 396 397 /* This is bad. */ 398 if ((pd = calloc(1, sizeof(*pd))) == NULL) { 399 printf("efipart_inithandles: Out of memory.\n"); 400 free(hin); 401 return (ENOMEM); 402 } 403 STAILQ_INIT(&pd->pd_part); 404 405 pd->pd_handle = hin[i]; 406 pd->pd_devpath = devpath; 407 pd->pd_blkio = blkio; 408 STAILQ_INSERT_TAIL(&pdinfo, pd, pd_link); 409 } 410 411 /* 412 * Walk pdinfo and set parents based on device path. 413 */ 414 STAILQ_FOREACH(pd, &pdinfo, pd_link) { 415 pd->pd_parent = efipart_find_parent(&pdinfo, pd->pd_devpath); 416 } 417 free(hin); 418 return (0); 419 } 420 421 /* 422 * Get node identified by pd_test() from plist. 423 */ 424 static pdinfo_t * 425 efipart_get_pd(pdinfo_list_t *plist, pd_test_cb_t pd_test, pdinfo_t *data) 426 { 427 pdinfo_t *pd; 428 429 STAILQ_FOREACH(pd, plist, pd_link) { 430 if (pd_test(pd, data)) 431 break; 432 } 433 434 return (pd); 435 } 436 437 static ACPI_HID_DEVICE_PATH * 438 efipart_floppy(EFI_DEVICE_PATH *node) 439 { 440 ACPI_HID_DEVICE_PATH *acpi; 441 442 if (DevicePathType(node) == ACPI_DEVICE_PATH && 443 DevicePathSubType(node) == ACPI_DP) { 444 acpi = (ACPI_HID_DEVICE_PATH *) node; 445 if (acpi->HID == EISA_PNP_ID(PNP0604) || 446 acpi->HID == EISA_PNP_ID(PNP0700) || 447 acpi->HID == EISA_PNP_ID(PNP0701)) { 448 return (acpi); 449 } 450 } 451 return (NULL); 452 } 453 454 static bool 455 efipart_testfd(pdinfo_t *fd, pdinfo_t *data __unused) 456 { 457 EFI_DEVICE_PATH *node; 458 459 node = efi_devpath_last_node(fd->pd_devpath); 460 if (node == NULL) 461 return (false); 462 463 if (efipart_floppy(node) != NULL) 464 return (true); 465 466 return (false); 467 } 468 469 static int 470 efipart_initfd(void) 471 { 472 EFI_DEVICE_PATH *node; 473 ACPI_HID_DEVICE_PATH *acpi; 474 pdinfo_t *parent, *fd; 475 476 while ((fd = efipart_get_pd(&pdinfo, efipart_testfd, NULL)) != NULL) { 477 if ((node = efi_devpath_last_node(fd->pd_devpath)) == NULL) 478 continue; 479 480 if ((acpi = efipart_floppy(node)) == NULL) 481 continue; 482 483 STAILQ_REMOVE(&pdinfo, fd, pdinfo, pd_link); 484 parent = fd->pd_parent; 485 if (parent != NULL) { 486 STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link); 487 parent->pd_alias = fd->pd_handle; 488 parent->pd_unit = acpi->UID; 489 free(fd); 490 fd = parent; 491 } else { 492 fd->pd_unit = acpi->UID; 493 } 494 fd->pd_devsw = &efipart_fddev; 495 STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link); 496 } 497 498 bcache_add_dev(efiblk_pdinfo_count(&fdinfo)); 499 return (0); 500 } 501 502 /* 503 * Add or update entries with new handle data. 504 */ 505 static void 506 efipart_cdinfo_add(pdinfo_t *cd) 507 { 508 pdinfo_t *parent, *pd, *last; 509 510 if (cd == NULL) 511 return; 512 513 parent = cd->pd_parent; 514 /* Make sure we have parent added */ 515 efipart_cdinfo_add(parent); 516 517 STAILQ_FOREACH(pd, &pdinfo, pd_link) { 518 if (efi_devpath_match(pd->pd_devpath, cd->pd_devpath)) { 519 STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link); 520 break; 521 } 522 } 523 if (pd == NULL) { 524 /* This device is already added. */ 525 return; 526 } 527 528 if (parent != NULL) { 529 last = STAILQ_LAST(&parent->pd_part, pdinfo, pd_link); 530 if (last != NULL) 531 cd->pd_unit = last->pd_unit + 1; 532 else 533 cd->pd_unit = 0; 534 cd->pd_devsw = &efipart_cddev; 535 STAILQ_INSERT_TAIL(&parent->pd_part, cd, pd_link); 536 return; 537 } 538 539 last = STAILQ_LAST(&cdinfo, pdinfo, pd_link); 540 if (last != NULL) 541 cd->pd_unit = last->pd_unit + 1; 542 else 543 cd->pd_unit = 0; 544 545 cd->pd_devsw = &efipart_cddev; 546 STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link); 547 } 548 549 static bool 550 efipart_testcd(pdinfo_t *cd, pdinfo_t *data __unused) 551 { 552 EFI_DEVICE_PATH *node; 553 554 node = efi_devpath_last_node(cd->pd_devpath); 555 if (node == NULL) 556 return (false); 557 558 if (efipart_floppy(node) != NULL) 559 return (false); 560 561 if (DevicePathType(node) == MEDIA_DEVICE_PATH && 562 DevicePathSubType(node) == MEDIA_CDROM_DP) { 563 return (true); 564 } 565 566 /* cd drive without the media. */ 567 if (cd->pd_blkio->Media->RemovableMedia && 568 !cd->pd_blkio->Media->MediaPresent) { 569 return (true); 570 } 571 572 return (false); 573 } 574 575 /* 576 * Test if pd is parent for device. 577 */ 578 static bool 579 efipart_testchild(pdinfo_t *dev, pdinfo_t *pd) 580 { 581 /* device with no parent. */ 582 if (dev->pd_parent == NULL) 583 return (false); 584 585 if (efi_devpath_match(dev->pd_parent->pd_devpath, pd->pd_devpath)) { 586 return (true); 587 } 588 return (false); 589 } 590 591 static int 592 efipart_initcd(void) 593 { 594 pdinfo_t *cd; 595 596 while ((cd = efipart_get_pd(&pdinfo, efipart_testcd, NULL)) != NULL) 597 efipart_cdinfo_add(cd); 598 599 /* Find all children of CD devices we did add above. */ 600 STAILQ_FOREACH(cd, &cdinfo, pd_link) { 601 pdinfo_t *child; 602 603 for (child = efipart_get_pd(&pdinfo, efipart_testchild, cd); 604 child != NULL; 605 child = efipart_get_pd(&pdinfo, efipart_testchild, cd)) 606 efipart_cdinfo_add(child); 607 } 608 bcache_add_dev(efiblk_pdinfo_count(&cdinfo)); 609 return (0); 610 } 611 612 static void 613 efipart_hdinfo_add_node(pdinfo_t *hd, EFI_DEVICE_PATH *node) 614 { 615 pdinfo_t *parent, *ptr; 616 617 if (node == NULL) 618 return; 619 620 parent = hd->pd_parent; 621 /* 622 * If the node is not MEDIA_HARDDRIVE_DP, it is sub-partition. 623 * This can happen with Vendor nodes, and since we do not know 624 * the more about those nodes, we just count them. 625 */ 626 if (DevicePathSubType(node) != MEDIA_HARDDRIVE_DP) { 627 ptr = STAILQ_LAST(&parent->pd_part, pdinfo, pd_link); 628 if (ptr != NULL) 629 hd->pd_unit = ptr->pd_unit + 1; 630 else 631 hd->pd_unit = 0; 632 } else { 633 hd->pd_unit = ((HARDDRIVE_DEVICE_PATH *)node)->PartitionNumber; 634 } 635 636 hd->pd_devsw = &efipart_hddev; 637 STAILQ_INSERT_TAIL(&parent->pd_part, hd, pd_link); 638 } 639 640 /* 641 * The MEDIA_FILEPATH_DP has device name. 642 * From U-Boot sources it looks like names are in the form 643 * of typeN:M, where type is interface type, N is disk id 644 * and M is partition id. 645 */ 646 static void 647 efipart_hdinfo_add_filepath(pdinfo_t *hd, FILEPATH_DEVICE_PATH *node) 648 { 649 char *pathname, *p; 650 int len; 651 pdinfo_t *last; 652 653 last = STAILQ_LAST(&hdinfo, pdinfo, pd_link); 654 if (last != NULL) 655 hd->pd_unit = last->pd_unit + 1; 656 else 657 hd->pd_unit = 0; 658 659 /* FILEPATH_DEVICE_PATH has 0 terminated string */ 660 len = ucs2len(node->PathName); 661 if ((pathname = malloc(len + 1)) == NULL) { 662 printf("Failed to add disk, out of memory\n"); 663 free(hd); 664 return; 665 } 666 cpy16to8(node->PathName, pathname, len + 1); 667 p = strchr(pathname, ':'); 668 669 /* 670 * Assume we are receiving handles in order, first disk handle, 671 * then partitions for this disk. If this assumption proves 672 * false, this code would need update. 673 */ 674 if (p == NULL) { /* no colon, add the disk */ 675 hd->pd_devsw = &efipart_hddev; 676 STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link); 677 free(pathname); 678 return; 679 } 680 p++; /* skip the colon */ 681 errno = 0; 682 hd->pd_unit = (int)strtol(p, NULL, 0); 683 if (errno != 0) { 684 printf("Bad unit number for partition \"%s\"\n", pathname); 685 free(pathname); 686 free(hd); 687 return; 688 } 689 690 /* 691 * We should have disk registered, if not, we are receiving 692 * handles out of order, and this code should be reworked 693 * to create "blank" disk for partition, and to find the 694 * disk based on PathName compares. 695 */ 696 if (last == NULL) { 697 printf("BUG: No disk for partition \"%s\"\n", pathname); 698 free(pathname); 699 free(hd); 700 return; 701 } 702 /* Add the partition. */ 703 hd->pd_parent = last; 704 hd->pd_devsw = &efipart_hddev; 705 STAILQ_INSERT_TAIL(&last->pd_part, hd, pd_link); 706 free(pathname); 707 } 708 709 static void 710 efipart_hdinfo_add(pdinfo_t *hd) 711 { 712 pdinfo_t *parent, *pd, *last; 713 EFI_DEVICE_PATH *node; 714 715 if (hd == NULL) 716 return; 717 718 parent = hd->pd_parent; 719 /* Make sure we have parent added */ 720 efipart_hdinfo_add(parent); 721 722 STAILQ_FOREACH(pd, &pdinfo, pd_link) { 723 if (efi_devpath_match(pd->pd_devpath, hd->pd_devpath)) { 724 STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link); 725 break; 726 } 727 } 728 if (pd == NULL) { 729 /* This device is already added. */ 730 return; 731 } 732 733 if ((node = efi_devpath_last_node(hd->pd_devpath)) == NULL) 734 return; 735 736 if (DevicePathType(node) == MEDIA_DEVICE_PATH && 737 DevicePathSubType(node) == MEDIA_FILEPATH_DP) { 738 efipart_hdinfo_add_filepath(hd, 739 (FILEPATH_DEVICE_PATH *)node); 740 return; 741 } 742 743 if (parent != NULL) { 744 efipart_hdinfo_add_node(hd, node); 745 return; 746 } 747 748 last = STAILQ_LAST(&hdinfo, pdinfo, pd_link); 749 if (last != NULL) 750 hd->pd_unit = last->pd_unit + 1; 751 else 752 hd->pd_unit = 0; 753 754 /* Add the disk. */ 755 hd->pd_devsw = &efipart_hddev; 756 STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link); 757 } 758 759 static bool 760 efipart_testhd(pdinfo_t *hd, pdinfo_t *data __unused) 761 { 762 if (efipart_testfd(hd, NULL)) 763 return (false); 764 765 if (efipart_testcd(hd, NULL)) 766 return (false); 767 768 /* Anything else must be HD. */ 769 return (true); 770 } 771 772 static int 773 efipart_inithd(void) 774 { 775 pdinfo_t *hd; 776 777 while ((hd = efipart_get_pd(&pdinfo, efipart_testhd, NULL)) != NULL) 778 efipart_hdinfo_add(hd); 779 780 bcache_add_dev(efiblk_pdinfo_count(&hdinfo)); 781 return (0); 782 } 783 784 static int 785 efipart_print_common(struct devsw *dev, pdinfo_list_t *pdlist, int verbose) 786 { 787 int ret = 0; 788 EFI_BLOCK_IO *blkio; 789 EFI_STATUS status; 790 EFI_HANDLE h; 791 pdinfo_t *pd; 792 CHAR16 *text; 793 struct disk_devdesc pd_dev; 794 char line[80]; 795 796 if (STAILQ_EMPTY(pdlist)) 797 return (0); 798 799 printf("%s devices:", dev->dv_name); 800 if ((ret = pager_output("\n")) != 0) 801 return (ret); 802 803 STAILQ_FOREACH(pd, pdlist, pd_link) { 804 h = pd->pd_handle; 805 if (verbose) { /* Output the device path. */ 806 text = efi_devpath_name(efi_lookup_devpath(h)); 807 if (text != NULL) { 808 printf(" %S", text); 809 efi_free_devpath_name(text); 810 if ((ret = pager_output("\n")) != 0) 811 break; 812 } 813 } 814 snprintf(line, sizeof(line), 815 " %s%d", dev->dv_name, pd->pd_unit); 816 printf("%s:", line); 817 status = OpenProtocolByHandle(h, &blkio_guid, (void **)&blkio); 818 if (!EFI_ERROR(status)) { 819 printf(" %llu", 820 blkio->Media->LastBlock == 0? 0: 821 (unsigned long long) (blkio->Media->LastBlock + 1)); 822 if (blkio->Media->LastBlock != 0) { 823 printf(" X %u", blkio->Media->BlockSize); 824 } 825 printf(" blocks"); 826 if (blkio->Media->MediaPresent) { 827 if (blkio->Media->RemovableMedia) 828 printf(" (removable)"); 829 } else { 830 printf(" (no media)"); 831 } 832 if ((ret = pager_output("\n")) != 0) 833 break; 834 if (!blkio->Media->MediaPresent) 835 continue; 836 837 pd->pd_blkio = blkio; 838 pd_dev.dd.d_dev = dev; 839 pd_dev.dd.d_unit = pd->pd_unit; 840 pd_dev.d_slice = D_SLICENONE; 841 pd_dev.d_partition = D_PARTNONE; 842 ret = disk_open(&pd_dev, blkio->Media->BlockSize * 843 (blkio->Media->LastBlock + 1), 844 blkio->Media->BlockSize); 845 if (ret == 0) { 846 ret = disk_print(&pd_dev, line, verbose); 847 disk_close(&pd_dev); 848 if (ret != 0) 849 return (ret); 850 } else { 851 /* Do not fail from disk_open() */ 852 ret = 0; 853 } 854 } else { 855 if ((ret = pager_output("\n")) != 0) 856 break; 857 } 858 } 859 return (ret); 860 } 861 862 static int 863 efipart_printfd(int verbose) 864 { 865 return (efipart_print_common(&efipart_fddev, &fdinfo, verbose)); 866 } 867 868 static int 869 efipart_printcd(int verbose) 870 { 871 return (efipart_print_common(&efipart_cddev, &cdinfo, verbose)); 872 } 873 874 static int 875 efipart_printhd(int verbose) 876 { 877 return (efipart_print_common(&efipart_hddev, &hdinfo, verbose)); 878 } 879 880 static int 881 efipart_open(struct open_file *f, ...) 882 { 883 va_list args; 884 struct disk_devdesc *dev; 885 pdinfo_t *pd; 886 EFI_BLOCK_IO *blkio; 887 EFI_STATUS status; 888 889 va_start(args, f); 890 dev = va_arg(args, struct disk_devdesc *); 891 va_end(args); 892 if (dev == NULL) 893 return (EINVAL); 894 895 pd = efiblk_get_pdinfo((struct devdesc *)dev); 896 if (pd == NULL) 897 return (EIO); 898 899 if (pd->pd_blkio == NULL) { 900 status = OpenProtocolByHandle(pd->pd_handle, &blkio_guid, 901 (void **)&pd->pd_blkio); 902 if (EFI_ERROR(status)) 903 return (efi_status_to_errno(status)); 904 } 905 906 blkio = pd->pd_blkio; 907 if (!blkio->Media->MediaPresent) 908 return (EAGAIN); 909 910 pd->pd_open++; 911 if (pd->pd_bcache == NULL) 912 pd->pd_bcache = bcache_allocate(); 913 914 if (dev->dd.d_dev->dv_type == DEVT_DISK) { 915 int rc; 916 917 rc = disk_open(dev, 918 blkio->Media->BlockSize * (blkio->Media->LastBlock + 1), 919 blkio->Media->BlockSize); 920 if (rc != 0) { 921 pd->pd_open--; 922 if (pd->pd_open == 0) { 923 pd->pd_blkio = NULL; 924 bcache_free(pd->pd_bcache); 925 pd->pd_bcache = NULL; 926 } 927 } 928 return (rc); 929 } 930 return (0); 931 } 932 933 static int 934 efipart_close(struct open_file *f) 935 { 936 struct disk_devdesc *dev; 937 pdinfo_t *pd; 938 939 dev = (struct disk_devdesc *)(f->f_devdata); 940 if (dev == NULL) 941 return (EINVAL); 942 943 pd = efiblk_get_pdinfo((struct devdesc *)dev); 944 if (pd == NULL) 945 return (EINVAL); 946 947 pd->pd_open--; 948 if (pd->pd_open == 0) { 949 pd->pd_blkio = NULL; 950 bcache_free(pd->pd_bcache); 951 pd->pd_bcache = NULL; 952 } 953 if (dev->dd.d_dev->dv_type == DEVT_DISK) 954 return (disk_close(dev)); 955 return (0); 956 } 957 958 static int 959 efipart_ioctl(struct open_file *f, u_long cmd, void *data) 960 { 961 struct disk_devdesc *dev; 962 pdinfo_t *pd; 963 int rc; 964 965 dev = (struct disk_devdesc *)(f->f_devdata); 966 if (dev == NULL) 967 return (EINVAL); 968 969 pd = efiblk_get_pdinfo((struct devdesc *)dev); 970 if (pd == NULL) 971 return (EINVAL); 972 973 if (dev->dd.d_dev->dv_type == DEVT_DISK) { 974 rc = disk_ioctl(dev, cmd, data); 975 if (rc != ENOTTY) 976 return (rc); 977 } 978 979 switch (cmd) { 980 case DIOCGSECTORSIZE: 981 *(u_int *)data = pd->pd_blkio->Media->BlockSize; 982 break; 983 case DIOCGMEDIASIZE: 984 *(uint64_t *)data = pd->pd_blkio->Media->BlockSize * 985 (pd->pd_blkio->Media->LastBlock + 1); 986 break; 987 default: 988 return (ENOTTY); 989 } 990 991 return (0); 992 } 993 994 /* 995 * efipart_readwrite() 996 * Internal equivalent of efipart_strategy(), which operates on the 997 * media-native block size. This function expects all I/O requests 998 * to be within the media size and returns an error if such is not 999 * the case. 1000 */ 1001 static int 1002 efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks, 1003 char *buf) 1004 { 1005 EFI_STATUS status; 1006 1007 if (blkio == NULL) 1008 return (ENXIO); 1009 if (blk < 0 || blk > blkio->Media->LastBlock) 1010 return (EIO); 1011 if ((blk + nblks - 1) > blkio->Media->LastBlock) 1012 return (EIO); 1013 1014 switch (rw & F_MASK) { 1015 case F_READ: 1016 status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk, 1017 nblks * blkio->Media->BlockSize, buf); 1018 break; 1019 case F_WRITE: 1020 if (blkio->Media->ReadOnly) 1021 return (EROFS); 1022 status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk, 1023 nblks * blkio->Media->BlockSize, buf); 1024 break; 1025 default: 1026 return (ENOSYS); 1027 } 1028 1029 if (EFI_ERROR(status)) { 1030 printf("%s: rw=%d, blk=%ju size=%ju status=%lu\n", __func__, rw, 1031 blk, nblks, EFI_ERROR_CODE(status)); 1032 } 1033 return (efi_status_to_errno(status)); 1034 } 1035 1036 static int 1037 efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, 1038 char *buf, size_t *rsize) 1039 { 1040 struct bcache_devdata bcd; 1041 struct disk_devdesc *dev; 1042 pdinfo_t *pd; 1043 1044 dev = (struct disk_devdesc *)devdata; 1045 if (dev == NULL) 1046 return (EINVAL); 1047 1048 pd = efiblk_get_pdinfo((struct devdesc *)dev); 1049 if (pd == NULL) 1050 return (EINVAL); 1051 1052 if (pd->pd_blkio->Media->RemovableMedia && 1053 !pd->pd_blkio->Media->MediaPresent) 1054 return (ENXIO); 1055 1056 bcd.dv_strategy = efipart_realstrategy; 1057 bcd.dv_devdata = devdata; 1058 bcd.dv_cache = pd->pd_bcache; 1059 1060 if (dev->dd.d_dev->dv_type == DEVT_DISK) { 1061 daddr_t offset; 1062 1063 offset = dev->d_offset * pd->pd_blkio->Media->BlockSize; 1064 offset /= 512; 1065 return (bcache_strategy(&bcd, rw, blk + offset, 1066 size, buf, rsize)); 1067 } 1068 return (bcache_strategy(&bcd, rw, blk, size, buf, rsize)); 1069 } 1070 1071 static int 1072 efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size, 1073 char *buf, size_t *rsize) 1074 { 1075 struct disk_devdesc *dev = (struct disk_devdesc *)devdata; 1076 pdinfo_t *pd; 1077 EFI_BLOCK_IO *blkio; 1078 uint64_t off, disk_blocks, d_offset = 0; 1079 char *blkbuf; 1080 size_t blkoff, blksz, bio_size; 1081 unsigned ioalign; 1082 bool need_buf; 1083 int rc; 1084 uint64_t diskend, readstart; 1085 1086 if (dev == NULL || blk < 0) 1087 return (EINVAL); 1088 1089 pd = efiblk_get_pdinfo((struct devdesc *)dev); 1090 if (pd == NULL) 1091 return (EINVAL); 1092 1093 blkio = pd->pd_blkio; 1094 if (blkio == NULL) 1095 return (ENXIO); 1096 1097 if (size == 0 || (size % 512) != 0) 1098 return (EIO); 1099 1100 off = blk * 512; 1101 /* 1102 * Get disk blocks, this value is either for whole disk or for 1103 * partition. 1104 */ 1105 disk_blocks = 0; 1106 if (dev->dd.d_dev->dv_type == DEVT_DISK) { 1107 if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) { 1108 /* DIOCGMEDIASIZE does return bytes. */ 1109 disk_blocks /= blkio->Media->BlockSize; 1110 } 1111 d_offset = dev->d_offset; 1112 } 1113 if (disk_blocks == 0) 1114 disk_blocks = blkio->Media->LastBlock + 1 - d_offset; 1115 1116 /* make sure we don't read past disk end */ 1117 if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) { 1118 diskend = d_offset + disk_blocks; 1119 readstart = off / blkio->Media->BlockSize; 1120 1121 if (diskend <= readstart) { 1122 if (rsize != NULL) 1123 *rsize = 0; 1124 1125 return (EIO); 1126 } 1127 size = diskend - readstart; 1128 size = size * blkio->Media->BlockSize; 1129 } 1130 1131 need_buf = true; 1132 /* Do we need bounce buffer? */ 1133 if ((size % blkio->Media->BlockSize == 0) && 1134 (off % blkio->Media->BlockSize == 0)) 1135 need_buf = false; 1136 1137 /* Do we have IO alignment requirement? */ 1138 ioalign = blkio->Media->IoAlign; 1139 if (ioalign == 0) 1140 ioalign++; 1141 1142 if (ioalign > 1 && (uintptr_t)buf != roundup2((uintptr_t)buf, ioalign)) 1143 need_buf = true; 1144 1145 if (need_buf) { 1146 for (bio_size = BIO_BUFFER_SIZE; bio_size > 0; 1147 bio_size -= blkio->Media->BlockSize) { 1148 blkbuf = memalign(ioalign, bio_size); 1149 if (blkbuf != NULL) 1150 break; 1151 } 1152 } else { 1153 blkbuf = buf; 1154 bio_size = size; 1155 } 1156 1157 if (blkbuf == NULL) 1158 return (ENOMEM); 1159 1160 if (rsize != NULL) 1161 *rsize = size; 1162 1163 rc = 0; 1164 blk = off / blkio->Media->BlockSize; 1165 blkoff = off % blkio->Media->BlockSize; 1166 1167 while (size > 0) { 1168 size_t x = min(size, bio_size); 1169 1170 if (x < blkio->Media->BlockSize) 1171 x = 1; 1172 else 1173 x /= blkio->Media->BlockSize; 1174 1175 switch (rw & F_MASK) { 1176 case F_READ: 1177 blksz = blkio->Media->BlockSize * x - blkoff; 1178 if (size < blksz) 1179 blksz = size; 1180 1181 rc = efipart_readwrite(blkio, rw, blk, x, blkbuf); 1182 if (rc != 0) 1183 goto error; 1184 1185 if (need_buf) 1186 bcopy(blkbuf + blkoff, buf, blksz); 1187 break; 1188 case F_WRITE: 1189 rc = 0; 1190 if (blkoff != 0) { 1191 /* 1192 * We got offset to sector, read 1 sector to 1193 * blkbuf. 1194 */ 1195 x = 1; 1196 blksz = blkio->Media->BlockSize - blkoff; 1197 blksz = min(blksz, size); 1198 rc = efipart_readwrite(blkio, F_READ, blk, x, 1199 blkbuf); 1200 } else if (size < blkio->Media->BlockSize) { 1201 /* 1202 * The remaining block is not full 1203 * sector. Read 1 sector to blkbuf. 1204 */ 1205 x = 1; 1206 blksz = size; 1207 rc = efipart_readwrite(blkio, F_READ, blk, x, 1208 blkbuf); 1209 } else { 1210 /* We can write full sector(s). */ 1211 blksz = blkio->Media->BlockSize * x; 1212 } 1213 1214 if (rc != 0) 1215 goto error; 1216 /* 1217 * Put your Data In, Put your Data out, 1218 * Put your Data In, and shake it all about 1219 */ 1220 if (need_buf) 1221 bcopy(buf, blkbuf + blkoff, blksz); 1222 rc = efipart_readwrite(blkio, F_WRITE, blk, x, blkbuf); 1223 if (rc != 0) 1224 goto error; 1225 break; 1226 default: 1227 /* DO NOTHING */ 1228 rc = EROFS; 1229 goto error; 1230 } 1231 1232 blkoff = 0; 1233 buf += blksz; 1234 size -= blksz; 1235 blk += x; 1236 } 1237 1238 error: 1239 if (rsize != NULL) 1240 *rsize -= size; 1241 1242 if (need_buf) 1243 free(blkbuf); 1244 return (rc); 1245 } 1246