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