1 /* $NetBSD: devopen.c,v 1.5 2018/04/11 10:32:09 nonaka Exp $ */ 2 3 /*- 4 * Copyright (c) 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Bang Jun-Young. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Copyright (c) 1996, 1997 34 * Matthias Drochner. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 50 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 51 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 52 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 55 */ 56 57 #include "efiboot.h" 58 59 #include <lib/libsa/dev_net.h> 60 61 #include <biosdisk.h> 62 #include "devopen.h" 63 #include <bootinfo.h> 64 #include "efidisk.h" 65 66 static int 67 dev2bios(char *devname, int unit, int *biosdev) 68 { 69 70 if (strcmp(devname, "hd") == 0) 71 *biosdev = 0x80 + unit; 72 else if (strcmp(devname, "cd") == 0) 73 *biosdev = 0x80 + get_harddrives() + unit; 74 else 75 return ENXIO; 76 77 return 0; 78 } 79 80 void 81 bios2dev(int biosdev, daddr_t sector, char **devname, int *unit, int *partition) 82 { 83 84 *unit = biosdev & 0x7f; 85 86 if (efi_bootdp_type == BOOT_DEVICE_TYPE_NET) { 87 *devname = "net"; 88 *unit = efi_net_get_booted_interface_unit(); 89 if (*unit < 0) 90 *unit = 0; 91 *partition = 0; 92 return; 93 } else if (biosdev >= 0x80 + get_harddrives()) { 94 *devname = "cd"; 95 *unit -= get_harddrives(); 96 } else 97 *devname = "hd"; 98 99 *partition = biosdisk_findpartition(biosdev, sector); 100 } 101 102 struct btinfo_bootpath bibp; 103 extern bool kernel_loaded; 104 105 /* 106 * Open the EFI disk device 107 */ 108 int 109 devopen(struct open_file *f, const char *fname, char **file) 110 { 111 #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) 112 static const char *net_devnames[] = { 113 #if defined(SUPPORT_NFS) 114 "nfs", 115 #endif 116 #if defined(SUPPORT_TFTP) 117 "tftp", 118 #endif 119 }; 120 #endif 121 struct devdesc desc; 122 struct devsw *dev; 123 char *fsname, *devname; 124 int unit, partition; 125 int biosdev; 126 int i, n, error; 127 128 error = parsebootfile(fname, &fsname, &devname, &unit, &partition, 129 (const char **) file); 130 if (error) 131 return error; 132 133 memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys); 134 nfsys = nfsys_disk; 135 136 #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP) 137 for (i = 0; i < __arraycount(net_devnames); i++) { 138 if (strcmp(devname, net_devnames[i]) == 0) { 139 fsname = devname; 140 devname = "net"; 141 break; 142 } 143 } 144 #endif 145 146 for (i = 1; i < ndevs; i++) { 147 dev = &devsw[i]; 148 if (strcmp(devname, DEV_NAME(dev)) == 0) { 149 if (strcmp(devname, "net") == 0) { 150 n = 0; 151 #if defined(SUPPORT_NFS) 152 if (strcmp(fsname, "nfs") == 0) { 153 memcpy(&file_system[n++], &file_system_nfs, 154 sizeof(file_system_nfs)); 155 } else 156 #endif 157 #if defined(SUPPORT_TFTP) 158 if (strcmp(fsname, "tftp") == 0) { 159 memcpy(&file_system[n++], &file_system_tftp, 160 sizeof(file_system_tftp)); 161 } else 162 #endif 163 { 164 #if defined(SUPPORT_NFS) 165 memcpy(&file_system[n++], &file_system_nfs, 166 sizeof(file_system_nfs)); 167 #endif 168 #if defined(SUPPORT_TFTP) 169 memcpy(&file_system[n++], &file_system_tftp, 170 sizeof(file_system_tftp)); 171 #endif 172 } 173 nfsys = n; 174 175 try_bootp = 1; 176 } 177 178 memset(&desc, 0, sizeof(desc)); 179 strlcpy(desc.d_name, devname, sizeof(desc.d_name)); 180 desc.d_unit = unit; 181 182 f->f_dev = dev; 183 if (!kernel_loaded) { 184 strncpy(bibp.bootpath, *file, 185 sizeof(bibp.bootpath)); 186 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); 187 } 188 return DEV_OPEN(f->f_dev)(f, &desc); 189 } 190 } 191 192 /* 193 * biosdisk 194 */ 195 if (strcmp(devname, "esp") == 0) { 196 bios2dev(boot_biosdev, boot_biossector, &devname, &unit, 197 &partition); 198 if (efidisk_get_efi_system_partition(boot_biosdev, &partition)) 199 return ENXIO; 200 } 201 202 error = dev2bios(devname, unit, &biosdev); 203 if (error) 204 return error; 205 206 f->f_dev = &devsw[0]; /* must be biosdisk */ 207 208 if (!kernel_loaded) { 209 strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath)); 210 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp)); 211 } 212 213 return biosdisk_open(f, biosdev, partition); 214 } 215