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