devopen.c revision 1.5.6.1 1 /* $NetBSD: devopen.c,v 1.5.6.1 2019/09/13 07:00:13 martin 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,
82 int *partition, const char **part_name)
83 {
84 static char savedevname[MAXDEVNAME+1];
85
86 *unit = biosdev & 0x7f;
87
88 if (efi_bootdp_type == BOOT_DEVICE_TYPE_NET) {
89 *devname = "net";
90 *unit = efi_net_get_booted_interface_unit();
91 if (*unit < 0)
92 *unit = 0;
93 *partition = 0;
94 return;
95 } else if (biosdev >= 0x80 + get_harddrives()) {
96 *devname = "cd";
97 *unit -= get_harddrives();
98 } else
99 *devname = "hd";
100
101 (void)biosdisk_findpartition(biosdev, sector, partition, part_name);
102 if (*part_name != NULL) {
103 snprintf(savedevname, sizeof(savedevname),
104 "NAME=%s", *part_name);
105 *devname = savedevname;
106 }
107 }
108
109 struct btinfo_bootpath bibp;
110 extern bool kernel_loaded;
111
112 /*
113 * Open the EFI disk device
114 */
115 int
116 devopen(struct open_file *f, const char *fname, char **file)
117 {
118 #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
119 static const char *net_devnames[] = {
120 #if defined(SUPPORT_NFS)
121 "nfs",
122 #endif
123 #if defined(SUPPORT_TFTP)
124 "tftp",
125 #endif
126 };
127 #endif
128 struct devdesc desc;
129 struct devsw *dev;
130 char *fsname, *devname;
131 int unit, partition;
132 int biosdev;
133 int i, n, error;
134
135 error = parsebootfile(fname, &fsname, &devname, &unit, &partition,
136 (const char **) file);
137 if (error)
138 return error;
139
140 /* Search by GPT label or raidframe name */
141 if ((strstr(devname, "NAME=") == devname) ||
142 (strstr(devname, "raid") == devname)) {
143 f->f_dev = &devsw[0]; /* must be biosdisk */
144
145 if (!kernel_loaded) {
146 strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
147 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
148 }
149
150 error = biosdisk_open_name(f, devname);
151 return error;
152 }
153
154 memcpy(file_system, file_system_disk, sizeof(*file_system) * nfsys);
155 nfsys = nfsys_disk;
156
157 #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
158 for (i = 0; i < __arraycount(net_devnames); i++) {
159 if (strcmp(devname, net_devnames[i]) == 0) {
160 fsname = devname;
161 devname = "net";
162 break;
163 }
164 }
165 #endif
166
167 for (i = 1; i < ndevs; i++) {
168 dev = &devsw[i];
169 if (strcmp(devname, DEV_NAME(dev)) == 0) {
170 if (strcmp(devname, "net") == 0) {
171 n = 0;
172 #if defined(SUPPORT_NFS)
173 if (strcmp(fsname, "nfs") == 0) {
174 memcpy(&file_system[n++], &file_system_nfs,
175 sizeof(file_system_nfs));
176 } else
177 #endif
178 #if defined(SUPPORT_TFTP)
179 if (strcmp(fsname, "tftp") == 0) {
180 memcpy(&file_system[n++], &file_system_tftp,
181 sizeof(file_system_tftp));
182 } else
183 #endif
184 {
185 #if defined(SUPPORT_NFS)
186 memcpy(&file_system[n++], &file_system_nfs,
187 sizeof(file_system_nfs));
188 #endif
189 #if defined(SUPPORT_TFTP)
190 memcpy(&file_system[n++], &file_system_tftp,
191 sizeof(file_system_tftp));
192 #endif
193 }
194 nfsys = n;
195
196 try_bootp = 1;
197 }
198
199 memset(&desc, 0, sizeof(desc));
200 strlcpy(desc.d_name, devname, sizeof(desc.d_name));
201 desc.d_unit = unit;
202
203 f->f_dev = dev;
204 if (!kernel_loaded) {
205 strncpy(bibp.bootpath, *file,
206 sizeof(bibp.bootpath));
207 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
208 }
209 return DEV_OPEN(f->f_dev)(f, &desc);
210 }
211 }
212
213 /*
214 * biosdisk
215 */
216 if (strcmp(devname, "esp") == 0) {
217 bios2dev(boot_biosdev, boot_biossector, &devname, &unit,
218 &partition, NULL);
219 if (efidisk_get_efi_system_partition(boot_biosdev, &partition))
220 return ENXIO;
221 }
222
223 error = dev2bios(devname, unit, &biosdev);
224 if (error)
225 return error;
226
227 f->f_dev = &devsw[0]; /* must be biosdisk */
228
229 if (!kernel_loaded) {
230 strncpy(bibp.bootpath, *file, sizeof(bibp.bootpath));
231 BI_ADD(&bibp, BTINFO_BOOTPATH, sizeof(bibp));
232 }
233
234 return biosdisk_open(f, biosdev, partition);
235 }
236