Home | History | Annotate | Line # | Download | only in efiboot
efidisk.c revision 1.1
      1 /*	$NetBSD: efidisk.c,v 1.1 2017/01/24 11:09:14 nonaka Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2016 Kimihiro Nonaka <nonaka (at) netbsd.org>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include "efiboot.h"
     30 
     31 #include "efidisk.h"
     32 
     33 static struct efidiskinfo_lh efi_disklist;
     34 static int nefidisks;
     35 
     36 void
     37 efi_disk_probe(void)
     38 {
     39 	EFI_STATUS status;
     40 	UINTN i, nhandles;
     41 	EFI_HANDLE *handles;
     42 	EFI_BLOCK_IO *bio;
     43 	EFI_BLOCK_IO_MEDIA *media;
     44 	struct efidiskinfo *edi;
     45 	EFI_DEVICE_PATH *dp, *bdp;
     46 	bool bootdev;
     47 	int dev;
     48 
     49 	TAILQ_INIT(&efi_disklist);
     50 
     51 	status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL,
     52 	    &nhandles, &handles);
     53 	if (EFI_ERROR(status))
     54 		Panic(L"LocateHandle(BlockIoProtocol): %r", status);
     55 
     56 	for (i = 0; i < nhandles; i++) {
     57 		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
     58 		    &BlockIoProtocol, (void **)&bio);
     59 		if (EFI_ERROR(status))
     60 			Panic(L"HandleProtocol(BlockIoProtocol): %r", status);
     61 
     62 		media = bio->Media;
     63 		if (media->LogicalPartition || !media->MediaPresent)
     64 			continue;
     65 
     66 		edi = alloc(sizeof(struct efidiskinfo));
     67 		memset(edi, 0, sizeof(*edi));
     68 		edi->bio = bio;
     69 		edi->media_id = media->MediaId;
     70 
     71 		bootdev = false;
     72 		if (efi_bootdp == NULL)
     73 			goto next;
     74 
     75 		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
     76 		    &DevicePathProtocol, (void **)&dp);
     77 		if (EFI_ERROR(status))
     78 			goto next;
     79 
     80 		bdp = efi_bootdp;
     81 		for (;;) {
     82 			if (IsDevicePathEnd(dp)) {
     83 				bootdev = true;
     84 				break;
     85 			}
     86 			if (memcmp(dp, bdp, sizeof(EFI_DEVICE_PATH)) != 0 ||
     87 			    memcmp(dp, bdp, DevicePathNodeLength(dp)) != 0)
     88 				break;
     89 			dp = NextDevicePathNode(dp);
     90 			bdp = NextDevicePathNode(bdp);
     91 		}
     92 next:
     93 		if (bootdev)
     94 			TAILQ_INSERT_HEAD(&efi_disklist, edi, list);
     95 		else
     96 			TAILQ_INSERT_TAIL(&efi_disklist, edi, list);
     97 	}
     98 
     99 	FreePool(handles);
    100 
    101 	dev = 0x80;
    102 	TAILQ_FOREACH(edi, &efi_disklist, list) {
    103 		edi->dev = dev++;
    104 		nefidisks++;
    105 	}
    106 }
    107 
    108 const struct efidiskinfo *
    109 efidisk_getinfo(int dev)
    110 {
    111 	const struct efidiskinfo *edi;
    112 
    113 	TAILQ_FOREACH(edi, &efi_disklist, list) {
    114 		if (dev == edi->dev)
    115 			return edi;
    116 	}
    117 	return NULL;
    118 }
    119 
    120 /*
    121  * Return the number of hard disk drives.
    122  */
    123 int
    124 get_harddrives(void)
    125 {
    126 	return nefidisks;
    127 }
    128