Home | History | Annotate | Line # | Download | only in efiboot
efidisk.c revision 1.3
      1  1.3  nonaka /*	$NetBSD: efidisk.c,v 1.3 2018/03/20 10:19:33 nonaka Exp $	*/
      2  1.1  nonaka 
      3  1.1  nonaka /*-
      4  1.1  nonaka  * Copyright (c) 2016 Kimihiro Nonaka <nonaka (at) netbsd.org>
      5  1.1  nonaka  * All rights reserved.
      6  1.1  nonaka  *
      7  1.1  nonaka  * Redistribution and use in source and binary forms, with or without
      8  1.1  nonaka  * modification, are permitted provided that the following conditions
      9  1.1  nonaka  * are met:
     10  1.1  nonaka  * 1. Redistributions of source code must retain the above copyright
     11  1.1  nonaka  *    notice, this list of conditions and the following disclaimer.
     12  1.1  nonaka  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  nonaka  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  nonaka  *    documentation and/or other materials provided with the distribution.
     15  1.1  nonaka  *
     16  1.1  nonaka  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17  1.1  nonaka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  1.1  nonaka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19  1.1  nonaka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20  1.1  nonaka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  1.1  nonaka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  1.1  nonaka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.1  nonaka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  1.1  nonaka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  1.1  nonaka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  1.1  nonaka  * SUCH DAMAGE.
     27  1.1  nonaka  */
     28  1.1  nonaka 
     29  1.2  nonaka #define FSTYPENAMES	/* for sys/disklabel.h */
     30  1.2  nonaka 
     31  1.1  nonaka #include "efiboot.h"
     32  1.1  nonaka 
     33  1.2  nonaka #include <sys/disklabel.h>
     34  1.2  nonaka 
     35  1.2  nonaka #include "biosdisk.h"
     36  1.2  nonaka #include "biosdisk_ll.h"
     37  1.2  nonaka #include "devopen.h"
     38  1.1  nonaka #include "efidisk.h"
     39  1.1  nonaka 
     40  1.1  nonaka static struct efidiskinfo_lh efi_disklist;
     41  1.1  nonaka static int nefidisks;
     42  1.1  nonaka 
     43  1.1  nonaka void
     44  1.1  nonaka efi_disk_probe(void)
     45  1.1  nonaka {
     46  1.1  nonaka 	EFI_STATUS status;
     47  1.1  nonaka 	UINTN i, nhandles;
     48  1.1  nonaka 	EFI_HANDLE *handles;
     49  1.1  nonaka 	EFI_BLOCK_IO *bio;
     50  1.1  nonaka 	EFI_BLOCK_IO_MEDIA *media;
     51  1.2  nonaka 	EFI_DEVICE_PATH *dp;
     52  1.1  nonaka 	struct efidiskinfo *edi;
     53  1.2  nonaka 	int dev, depth = -1;
     54  1.1  nonaka 
     55  1.1  nonaka 	TAILQ_INIT(&efi_disklist);
     56  1.1  nonaka 
     57  1.1  nonaka 	status = LibLocateHandle(ByProtocol, &BlockIoProtocol, NULL,
     58  1.1  nonaka 	    &nhandles, &handles);
     59  1.1  nonaka 	if (EFI_ERROR(status))
     60  1.1  nonaka 		Panic(L"LocateHandle(BlockIoProtocol): %r", status);
     61  1.1  nonaka 
     62  1.2  nonaka 	if (efi_bootdp != NULL)
     63  1.2  nonaka 		depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH);
     64  1.2  nonaka 
     65  1.2  nonaka 	/*
     66  1.2  nonaka 	 * U-Boot incorrectly represents devices with a single
     67  1.2  nonaka 	 * MEDIA_DEVICE_PATH component.  In that case include that
     68  1.2  nonaka 	 * component into the matching, otherwise we'll blindly select
     69  1.2  nonaka 	 * the first device.
     70  1.2  nonaka 	 */
     71  1.2  nonaka 	if (depth == 0)
     72  1.2  nonaka 		depth = 1;
     73  1.2  nonaka 
     74  1.1  nonaka 	for (i = 0; i < nhandles; i++) {
     75  1.1  nonaka 		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
     76  1.1  nonaka 		    &BlockIoProtocol, (void **)&bio);
     77  1.1  nonaka 		if (EFI_ERROR(status))
     78  1.1  nonaka 			Panic(L"HandleProtocol(BlockIoProtocol): %r", status);
     79  1.1  nonaka 
     80  1.1  nonaka 		media = bio->Media;
     81  1.1  nonaka 		if (media->LogicalPartition || !media->MediaPresent)
     82  1.1  nonaka 			continue;
     83  1.1  nonaka 
     84  1.1  nonaka 		edi = alloc(sizeof(struct efidiskinfo));
     85  1.1  nonaka 		memset(edi, 0, sizeof(*edi));
     86  1.2  nonaka 		edi->type = BIOSDISK_TYPE_HD;
     87  1.1  nonaka 		edi->bio = bio;
     88  1.1  nonaka 		edi->media_id = media->MediaId;
     89  1.1  nonaka 
     90  1.2  nonaka 		if (efi_bootdp != NULL && depth > 0) {
     91  1.2  nonaka 			status = uefi_call_wrapper(BS->HandleProtocol, 3,
     92  1.2  nonaka 			    handles[i], &DevicePathProtocol, (void **)&dp);
     93  1.2  nonaka 			if (EFI_ERROR(status))
     94  1.2  nonaka 				goto next;
     95  1.2  nonaka 			if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) {
     96  1.2  nonaka 				edi->bootdev = true;
     97  1.2  nonaka 				TAILQ_INSERT_HEAD(&efi_disklist, edi,
     98  1.2  nonaka 				    list);
     99  1.2  nonaka 				continue;
    100  1.2  nonaka 			}
    101  1.2  nonaka 		}
    102  1.2  nonaka next:
    103  1.2  nonaka 		TAILQ_INSERT_TAIL(&efi_disklist, edi, list);
    104  1.2  nonaka 	}
    105  1.1  nonaka 
    106  1.2  nonaka 	FreePool(handles);
    107  1.1  nonaka 
    108  1.2  nonaka 	if (efi_bootdp_type == BIOSDISK_TYPE_CD) {
    109  1.3  nonaka 		edi = TAILQ_FIRST(&efi_disklist);
    110  1.3  nonaka 		if (edi != NULL && edi->bootdev) {
    111  1.3  nonaka 			edi->type = BIOSDISK_TYPE_CD;
    112  1.3  nonaka 			TAILQ_REMOVE(&efi_disklist, edi, list);
    113  1.3  nonaka 			TAILQ_INSERT_TAIL(&efi_disklist, edi, list);
    114  1.1  nonaka 		}
    115  1.1  nonaka 	}
    116  1.1  nonaka 
    117  1.1  nonaka 	dev = 0x80;
    118  1.1  nonaka 	TAILQ_FOREACH(edi, &efi_disklist, list) {
    119  1.1  nonaka 		edi->dev = dev++;
    120  1.2  nonaka 		if (edi->type == BIOSDISK_TYPE_HD)
    121  1.2  nonaka 			nefidisks++;
    122  1.2  nonaka 		if (edi->bootdev)
    123  1.2  nonaka 			boot_biosdev = edi->dev;
    124  1.2  nonaka 	}
    125  1.2  nonaka }
    126  1.2  nonaka 
    127  1.2  nonaka void
    128  1.2  nonaka efi_disk_show(void)
    129  1.2  nonaka {
    130  1.2  nonaka 	const struct efidiskinfo *edi;
    131  1.2  nonaka 	EFI_BLOCK_IO_MEDIA *media;
    132  1.2  nonaka 	struct biosdisk_partition *part;
    133  1.2  nonaka 	uint64_t size;
    134  1.2  nonaka 	int i, nparts;
    135  1.2  nonaka 	bool first;
    136  1.2  nonaka 
    137  1.2  nonaka 	TAILQ_FOREACH(edi, &efi_disklist, list) {
    138  1.2  nonaka 		media = edi->bio->Media;
    139  1.2  nonaka 		first = true;
    140  1.2  nonaka 		printf("disk ");
    141  1.2  nonaka 		switch (edi->type) {
    142  1.2  nonaka 		case BIOSDISK_TYPE_CD:
    143  1.2  nonaka 			printf("cd0");
    144  1.2  nonaka 			printf(" mediaId %u", media->MediaId);
    145  1.2  nonaka 			if (edi->media_id != media->MediaId)
    146  1.2  nonaka 				printf("(%u)", edi->media_id);
    147  1.2  nonaka 			printf("\n");
    148  1.2  nonaka 			printf("  cd0a\n");
    149  1.2  nonaka 			break;
    150  1.2  nonaka 		case BIOSDISK_TYPE_HD:
    151  1.2  nonaka 			printf("hd%d", edi->dev & 0x7f);
    152  1.2  nonaka 			printf(" mediaId %u", media->MediaId);
    153  1.2  nonaka 			if (edi->media_id != media->MediaId)
    154  1.2  nonaka 				printf("(%u)", edi->media_id);
    155  1.2  nonaka 			printf(" size ");
    156  1.2  nonaka 			size = (media->LastBlock + 1) * media->BlockSize;
    157  1.2  nonaka 			if (size >= (10ULL * 1024 * 1024 * 1024))
    158  1.2  nonaka 				printf("%"PRIu64" GB", size / (1024 * 1024 * 1024));
    159  1.2  nonaka 			else
    160  1.2  nonaka 				printf("%"PRIu64" MB", size / (1024 * 1024));
    161  1.2  nonaka 			printf("\n");
    162  1.2  nonaka 			break;
    163  1.2  nonaka 		}
    164  1.2  nonaka 		if (edi->type != BIOSDISK_TYPE_HD)
    165  1.2  nonaka 			continue;
    166  1.2  nonaka 
    167  1.2  nonaka 		if (biosdisk_readpartition(edi->dev, &part, &nparts))
    168  1.2  nonaka 			continue;
    169  1.2  nonaka 
    170  1.2  nonaka 		for (i = 0; i < nparts; i++) {
    171  1.2  nonaka 			if (part[i].size == 0)
    172  1.2  nonaka 				continue;
    173  1.2  nonaka 			if (part[i].fstype == FS_UNUSED)
    174  1.2  nonaka 				continue;
    175  1.2  nonaka 			if (first) {
    176  1.2  nonaka 				printf(" ");
    177  1.2  nonaka 				first = false;
    178  1.2  nonaka 			}
    179  1.2  nonaka 			printf(" hd%d%c(", edi->dev & 0x7f, i + 'a');
    180  1.2  nonaka 			if (part[i].guid != NULL)
    181  1.2  nonaka 				printf("%s", part[i].guid->name);
    182  1.2  nonaka 			else if (part[i].fstype < FSMAXTYPES)
    183  1.2  nonaka 				printf("%s", fstypenames[part[i].fstype]);
    184  1.2  nonaka 			else
    185  1.2  nonaka 				printf("%d", part[i].fstype);
    186  1.2  nonaka 			printf(")");
    187  1.2  nonaka 		}
    188  1.2  nonaka 		if (!first)
    189  1.2  nonaka 			printf("\n");
    190  1.2  nonaka 		dealloc(part, sizeof(*part) * nparts);
    191  1.1  nonaka 	}
    192  1.1  nonaka }
    193  1.1  nonaka 
    194  1.1  nonaka const struct efidiskinfo *
    195  1.1  nonaka efidisk_getinfo(int dev)
    196  1.1  nonaka {
    197  1.1  nonaka 	const struct efidiskinfo *edi;
    198  1.1  nonaka 
    199  1.1  nonaka 	TAILQ_FOREACH(edi, &efi_disklist, list) {
    200  1.1  nonaka 		if (dev == edi->dev)
    201  1.1  nonaka 			return edi;
    202  1.1  nonaka 	}
    203  1.1  nonaka 	return NULL;
    204  1.1  nonaka }
    205  1.1  nonaka 
    206  1.1  nonaka /*
    207  1.1  nonaka  * Return the number of hard disk drives.
    208  1.1  nonaka  */
    209  1.1  nonaka int
    210  1.1  nonaka get_harddrives(void)
    211  1.1  nonaka {
    212  1.1  nonaka 	return nefidisks;
    213  1.1  nonaka }
    214