xref: /netbsd-src/sys/arch/i386/stand/efiboot/devopen.c (revision c38e7cc395b1472a774ff828e46123de44c628e9)
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