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