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