View | Details | Raw Unified | Return to bug 219000
Collapse All | Expand All

(-)b/sys/boot/efi/libefi/efipart.c (-1 / +9 lines)
Lines 1-968 Link Here
1
/*-
1
/*-
2
 * Copyright (c) 2010 Marcel Moolenaar
2
 * Copyright (c) 2010 Marcel Moolenaar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
12
 *    documentation and/or other materials provided with the distribution.
13
 *
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
24
 * SUCH DAMAGE.
25
 */
25
 */
26
26
27
#include <sys/cdefs.h>
27
#include <sys/cdefs.h>
28
__FBSDID("$FreeBSD$");
28
__FBSDID("$FreeBSD$");
29
29
30
#include <sys/disk.h>
30
#include <sys/disk.h>
31
#include <sys/param.h>
31
#include <sys/param.h>
32
#include <sys/time.h>
32
#include <sys/time.h>
33
#include <sys/queue.h>
33
#include <sys/queue.h>
34
#include <stddef.h>
34
#include <stddef.h>
35
#include <stdarg.h>
35
#include <stdarg.h>
36
36
37
#include <bootstrap.h>
37
#include <bootstrap.h>
38
38
39
#include <efi.h>
39
#include <efi.h>
40
#include <efilib.h>
40
#include <efilib.h>
41
#include <efiprot.h>
41
#include <efiprot.h>
42
#include <disk.h>
42
#include <disk.h>
43
43
44
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
44
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
45
45
46
static int efipart_initfd(void);
46
static int efipart_initfd(void);
47
static int efipart_initcd(void);
47
static int efipart_initcd(void);
48
static int efipart_inithd(void);
48
static int efipart_inithd(void);
49
49
50
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
50
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
51
static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *);
51
static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *);
52
52
53
static int efipart_open(struct open_file *, ...);
53
static int efipart_open(struct open_file *, ...);
54
static int efipart_close(struct open_file *);
54
static int efipart_close(struct open_file *);
55
static int efipart_ioctl(struct open_file *, u_long, void *);
55
static int efipart_ioctl(struct open_file *, u_long, void *);
56
56
57
static int efipart_printfd(int);
57
static int efipart_printfd(int);
58
static int efipart_printcd(int);
58
static int efipart_printcd(int);
59
static int efipart_printhd(int);
59
static int efipart_printhd(int);
60
60
61
struct devsw efipart_fddev = {
61
struct devsw efipart_fddev = {
62
	.dv_name = "fd",
62
	.dv_name = "fd",
63
	.dv_type = DEVT_FD,
63
	.dv_type = DEVT_FD,
64
	.dv_init = efipart_initfd,
64
	.dv_init = efipart_initfd,
65
	.dv_strategy = efipart_strategy,
65
	.dv_strategy = efipart_strategy,
66
	.dv_open = efipart_open,
66
	.dv_open = efipart_open,
67
	.dv_close = efipart_close,
67
	.dv_close = efipart_close,
68
	.dv_ioctl = efipart_ioctl,
68
	.dv_ioctl = efipart_ioctl,
69
	.dv_print = efipart_printfd,
69
	.dv_print = efipart_printfd,
70
	.dv_cleanup = NULL
70
	.dv_cleanup = NULL
71
};
71
};
72
72
73
struct devsw efipart_cddev = {
73
struct devsw efipart_cddev = {
74
	.dv_name = "cd",
74
	.dv_name = "cd",
75
	.dv_type = DEVT_CD,
75
	.dv_type = DEVT_CD,
76
	.dv_init = efipart_initcd,
76
	.dv_init = efipart_initcd,
77
	.dv_strategy = efipart_strategy,
77
	.dv_strategy = efipart_strategy,
78
	.dv_open = efipart_open,
78
	.dv_open = efipart_open,
79
	.dv_close = efipart_close,
79
	.dv_close = efipart_close,
80
	.dv_ioctl = efipart_ioctl,
80
	.dv_ioctl = efipart_ioctl,
81
	.dv_print = efipart_printcd,
81
	.dv_print = efipart_printcd,
82
	.dv_cleanup = NULL
82
	.dv_cleanup = NULL
83
};
83
};
84
84
85
struct devsw efipart_hddev = {
85
struct devsw efipart_hddev = {
86
	.dv_name = "disk",
86
	.dv_name = "disk",
87
	.dv_type = DEVT_DISK,
87
	.dv_type = DEVT_DISK,
88
	.dv_init = efipart_inithd,
88
	.dv_init = efipart_inithd,
89
	.dv_strategy = efipart_strategy,
89
	.dv_strategy = efipart_strategy,
90
	.dv_open = efipart_open,
90
	.dv_open = efipart_open,
91
	.dv_close = efipart_close,
91
	.dv_close = efipart_close,
92
	.dv_ioctl = efipart_ioctl,
92
	.dv_ioctl = efipart_ioctl,
93
	.dv_print = efipart_printhd,
93
	.dv_print = efipart_printhd,
94
	.dv_cleanup = NULL
94
	.dv_cleanup = NULL
95
};
95
};
96
96
97
static pdinfo_list_t fdinfo;
97
static pdinfo_list_t fdinfo;
98
static pdinfo_list_t cdinfo;
98
static pdinfo_list_t cdinfo;
99
static pdinfo_list_t hdinfo;
99
static pdinfo_list_t hdinfo;
100
100
101
static EFI_HANDLE *efipart_handles = NULL;
101
static EFI_HANDLE *efipart_handles = NULL;
102
static UINTN efipart_nhandles = 0;
102
static UINTN efipart_nhandles = 0;
103
103
104
static pdinfo_t *
104
static pdinfo_t *
105
efiblk_get_pdinfo(pdinfo_list_t *pdi, int unit)
105
efiblk_get_pdinfo(pdinfo_list_t *pdi, int unit)
106
{
106
{
107
	pdinfo_t *pd;
107
	pdinfo_t *pd;
108
108
109
	STAILQ_FOREACH(pd, pdi, pd_link) {
109
	STAILQ_FOREACH(pd, pdi, pd_link) {
110
		if (pd->pd_unit == unit)
110
		if (pd->pd_unit == unit)
111
			return (pd);
111
			return (pd);
112
	}
112
	}
113
	return (NULL);
113
	return (NULL);
114
}
114
}
115
115
116
static int
116
static int
117
efiblk_pdinfo_count(pdinfo_list_t *pdi)
117
efiblk_pdinfo_count(pdinfo_list_t *pdi)
118
{
118
{
119
	pdinfo_t *pd;
119
	pdinfo_t *pd;
120
	int i = 0;
120
	int i = 0;
121
121
122
	STAILQ_FOREACH(pd, pdi, pd_link) {
122
	STAILQ_FOREACH(pd, pdi, pd_link) {
123
		i++;
123
		i++;
124
	}
124
	}
125
	return (i);
125
	return (i);
126
}
126
}
127
127
128
static int
128
static int
129
efipart_inithandles(void)
129
efipart_inithandles(void)
130
{
130
{
131
	UINTN sz;
131
	UINTN sz;
132
	EFI_HANDLE *hin;
132
	EFI_HANDLE *hin;
133
	EFI_STATUS status;
133
	EFI_STATUS status;
134
134
135
	if (efipart_nhandles != 0) {
135
	if (efipart_nhandles != 0) {
136
		free(efipart_handles);
136
		free(efipart_handles);
137
		efipart_handles = NULL;
137
		efipart_handles = NULL;
138
		efipart_nhandles = 0;
138
		efipart_nhandles = 0;
139
	}
139
	}
140
140
141
	sz = 0;
141
	sz = 0;
142
	hin = NULL;
142
	hin = NULL;
143
	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, hin);
143
	status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, hin);
144
	if (status == EFI_BUFFER_TOO_SMALL) {
144
	if (status == EFI_BUFFER_TOO_SMALL) {
145
		hin = malloc(sz);
145
		hin = malloc(sz);
146
		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
146
		status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
147
		    hin);
147
		    hin);
148
		if (EFI_ERROR(status))
148
		if (EFI_ERROR(status))
149
			free(hin);
149
			free(hin);
150
	}
150
	}
151
	if (EFI_ERROR(status))
151
	if (EFI_ERROR(status))
152
		return (efi_status_to_errno(status));
152
		return (efi_status_to_errno(status));
153
153
154
	efipart_handles = hin;
154
	efipart_handles = hin;
155
	efipart_nhandles = sz;
155
	efipart_nhandles = sz;
156
	return (0);
156
	return (0);
157
}
157
}
158
158
159
static ACPI_HID_DEVICE_PATH *
159
static ACPI_HID_DEVICE_PATH *
160
efipart_floppy(EFI_DEVICE_PATH *node)
160
efipart_floppy(EFI_DEVICE_PATH *node)
161
{
161
{
162
	ACPI_HID_DEVICE_PATH *acpi = NULL;
162
	ACPI_HID_DEVICE_PATH *acpi = NULL;
163
163
164
	if (DevicePathType(node) == ACPI_DEVICE_PATH &&
164
	if (DevicePathType(node) == ACPI_DEVICE_PATH &&
165
	    DevicePathSubType(node) == ACPI_DP) {
165
	    DevicePathSubType(node) == ACPI_DP) {
166
		acpi = (ACPI_HID_DEVICE_PATH *) node;
166
		acpi = (ACPI_HID_DEVICE_PATH *) node;
167
		if (acpi->HID == EISA_PNP_ID(0x604) ||
167
		if (acpi->HID == EISA_PNP_ID(0x604) ||
168
		    acpi->HID == EISA_PNP_ID(0x700) ||
168
		    acpi->HID == EISA_PNP_ID(0x700) ||
169
		    acpi->HID == EISA_ID(0x41d1, 0x701)) {
169
		    acpi->HID == EISA_ID(0x41d1, 0x701)) {
170
			return (acpi);
170
			return (acpi);
171
		}
171
		}
172
	}
172
	}
173
	return (acpi);
173
	return (acpi);
174
}
174
}
175
175
176
/*
176
/*
177
 * Add or update entries with new handle data.
177
 * Add or update entries with new handle data.
178
 */
178
 */
179
static int
179
static int
180
efipart_fdinfo_add(EFI_HANDLE handle, uint32_t uid, EFI_DEVICE_PATH *devpath)
180
efipart_fdinfo_add(EFI_HANDLE handle, uint32_t uid, EFI_DEVICE_PATH *devpath)
181
{
181
{
182
	pdinfo_t *fd;
182
	pdinfo_t *fd;
183
183
184
	fd = malloc(sizeof(pdinfo_t));
184
	fd = malloc(sizeof(pdinfo_t));
185
	if (fd == NULL) {
185
	if (fd == NULL) {
186
		printf("Failed to register floppy %d, out of memory\n", uid);
186
		printf("Failed to register floppy %d, out of memory\n", uid);
187
		return (ENOMEM);
187
		return (ENOMEM);
188
	}
188
	}
189
	memset(fd, 0, sizeof(pdinfo_t));
189
	memset(fd, 0, sizeof(pdinfo_t));
190
	STAILQ_INIT(&fd->pd_part);
190
	STAILQ_INIT(&fd->pd_part);
191
191
192
	fd->pd_unit = uid;
192
	fd->pd_unit = uid;
193
	fd->pd_handle = handle;
193
	fd->pd_handle = handle;
194
	fd->pd_devpath = devpath;
194
	fd->pd_devpath = devpath;
195
	STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
195
	STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
196
	return (0);
196
	return (0);
197
}
197
}
198
198
199
static void
199
static void
200
efipart_updatefd(void)
200
efipart_updatefd(void)
201
{
201
{
202
	EFI_DEVICE_PATH *devpath, *node;
202
	EFI_DEVICE_PATH *devpath, *node;
203
	ACPI_HID_DEVICE_PATH *acpi;
203
	ACPI_HID_DEVICE_PATH *acpi;
204
	int i, nin;
204
	int i, nin;
205
205
206
	nin = efipart_nhandles / sizeof (*efipart_handles);
206
	nin = efipart_nhandles / sizeof (*efipart_handles);
207
	for (i = 0; i < nin; i++) {
207
	for (i = 0; i < nin; i++) {
208
		devpath = efi_lookup_devpath(efipart_handles[i]);
208
		devpath = efi_lookup_devpath(efipart_handles[i]);
209
		if (devpath == NULL)
209
		if (devpath == NULL)
210
			continue;
210
			continue;
211
211
212
		if ((node = efi_devpath_last_node(devpath)) == NULL)
212
		if ((node = efi_devpath_last_node(devpath)) == NULL)
213
			continue;
213
			continue;
214
		if ((acpi = efipart_floppy(node)) != NULL) {
214
		if ((acpi = efipart_floppy(node)) != NULL) {
215
			efipart_fdinfo_add(efipart_handles[i], acpi->UID,
215
			efipart_fdinfo_add(efipart_handles[i], acpi->UID,
216
			    devpath);
216
			    devpath);
217
		}
217
		}
218
	}
218
	}
219
}
219
}
220
220
221
static int
221
static int
222
efipart_initfd(void)
222
efipart_initfd(void)
223
{
223
{
224
	int rv;
224
	int rv;
225
225
226
	rv = efipart_inithandles();
226
	rv = efipart_inithandles();
227
	if (rv != 0)
227
	if (rv != 0)
228
		return (rv);
228
		return (rv);
229
	STAILQ_INIT(&fdinfo);
229
	STAILQ_INIT(&fdinfo);
230
230
231
	efipart_updatefd();
231
	efipart_updatefd();
232
232
233
	bcache_add_dev(efiblk_pdinfo_count(&fdinfo));
233
	bcache_add_dev(efiblk_pdinfo_count(&fdinfo));
234
	return (0);
234
	return (0);
235
}
235
}
236
236
237
/*
237
/*
238
 * Add or update entries with new handle data.
238
 * Add or update entries with new handle data.
239
 */
239
 */
240
static int
240
static int
241
efipart_cdinfo_add(EFI_HANDLE handle, EFI_HANDLE alias,
241
efipart_cdinfo_add(EFI_HANDLE handle, EFI_HANDLE alias,
242
    EFI_DEVICE_PATH *devpath)
242
    EFI_DEVICE_PATH *devpath)
243
{
243
{
244
	int unit;
244
	int unit;
245
	pdinfo_t *cd;
245
	pdinfo_t *cd;
246
	pdinfo_t *pd;
246
	pdinfo_t *pd;
247
247
248
	unit = 0;
248
	unit = 0;
249
	STAILQ_FOREACH(pd, &cdinfo, pd_link) {
249
	STAILQ_FOREACH(pd, &cdinfo, pd_link) {
250
		if (efi_devpath_match(pd->pd_devpath, devpath) != 0) {
250
		if (efi_devpath_match(pd->pd_devpath, devpath) != 0) {
251
			pd->pd_handle = handle;
251
			pd->pd_handle = handle;
252
			pd->pd_alias = alias;
252
			pd->pd_alias = alias;
253
			return (0);
253
			return (0);
254
		}
254
		}
255
		unit++;
255
		unit++;
256
	}
256
	}
257
257
258
	cd = malloc(sizeof(pdinfo_t));
258
	cd = malloc(sizeof(pdinfo_t));
259
	if (cd == NULL) {
259
	if (cd == NULL) {
260
		printf("Failed to add cd %d, out of memory\n", unit);
260
		printf("Failed to add cd %d, out of memory\n", unit);
261
		return (ENOMEM);
261
		return (ENOMEM);
262
	}
262
	}
263
	memset(cd, 0, sizeof(pdinfo_t));
263
	memset(cd, 0, sizeof(pdinfo_t));
264
	STAILQ_INIT(&cd->pd_part);
264
	STAILQ_INIT(&cd->pd_part);
265
265
266
	cd->pd_handle = handle;
266
	cd->pd_handle = handle;
267
	cd->pd_unit = unit;
267
	cd->pd_unit = unit;
268
	cd->pd_alias = alias;
268
	cd->pd_alias = alias;
269
	cd->pd_devpath = devpath;
269
	cd->pd_devpath = devpath;
270
	STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
270
	STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
271
	return (0);
271
	return (0);
272
}
272
}
273
273
274
static void
274
static void
275
efipart_updatecd(void)
275
efipart_updatecd(void)
276
{
276
{
277
	int i, nin;
277
	int i, nin;
278
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
278
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
279
	EFI_HANDLE handle;
279
	EFI_HANDLE handle;
280
	EFI_BLOCK_IO *blkio;
280
	EFI_BLOCK_IO *blkio;
281
	EFI_STATUS status;
281
	EFI_STATUS status;
282
282
283
	nin = efipart_nhandles / sizeof (*efipart_handles);
283
	nin = efipart_nhandles / sizeof (*efipart_handles);
284
	for (i = 0; i < nin; i++) {
284
	for (i = 0; i < nin; i++) {
285
		devpath = efi_lookup_devpath(efipart_handles[i]);
285
		devpath = efi_lookup_devpath(efipart_handles[i]);
286
		if (devpath == NULL)
286
		if (devpath == NULL)
287
			continue;
287
			continue;
288
288
289
		if ((node = efi_devpath_last_node(devpath)) == NULL)
289
		if ((node = efi_devpath_last_node(devpath)) == NULL)
290
			continue;
290
			continue;
291
		if (efipart_floppy(node) != NULL)
291
		if (efipart_floppy(node) != NULL)
292
			continue;
292
			continue;
293
293
294
		status = BS->HandleProtocol(efipart_handles[i],
294
		status = BS->HandleProtocol(efipart_handles[i],
295
		    &blkio_guid, (void **)&blkio);
295
		    &blkio_guid, (void **)&blkio);
296
		if (EFI_ERROR(status))
296
		if (EFI_ERROR(status))
297
			continue;
297
			continue;
298
		/*
298
		/*
299
		 * If we come across a logical partition of subtype CDROM
299
		 * If we come across a logical partition of subtype CDROM
300
		 * it doesn't refer to the CD filesystem itself, but rather
300
		 * it doesn't refer to the CD filesystem itself, but rather
301
		 * to any usable El Torito boot image on it. In this case
301
		 * to any usable El Torito boot image on it. In this case
302
		 * we try to find the parent device and add that instead as
302
		 * we try to find the parent device and add that instead as
303
		 * that will be the CD filesystem.
303
		 * that will be the CD filesystem.
304
		 */
304
		 */
305
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
305
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
306
		    DevicePathSubType(node) == MEDIA_CDROM_DP) {
306
		    DevicePathSubType(node) == MEDIA_CDROM_DP) {
307
			devpathcpy = efi_devpath_trim(devpath);
307
			devpathcpy = efi_devpath_trim(devpath);
308
			if (devpathcpy == NULL)
308
			if (devpathcpy == NULL)
309
				continue;
309
				continue;
310
			tmpdevpath = devpathcpy;
310
			tmpdevpath = devpathcpy;
311
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
311
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
312
			    &handle);
312
			    &handle);
313
			free(devpathcpy);
313
			free(devpathcpy);
314
			if (EFI_ERROR(status))
314
			if (EFI_ERROR(status))
315
				continue;
315
				continue;
316
			devpath = efi_lookup_devpath(handle);
316
			devpath = efi_lookup_devpath(handle);
317
			efipart_cdinfo_add(handle, efipart_handles[i],
317
			efipart_cdinfo_add(handle, efipart_handles[i],
318
			    devpath);
318
			    devpath);
319
			continue;
319
			continue;
320
		}
320
		}
321
321
322
		if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
322
		if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
323
		    DevicePathSubType(node) == MSG_ATAPI_DP) {
323
		    DevicePathSubType(node) == MSG_ATAPI_DP) {
324
			efipart_cdinfo_add(efipart_handles[i], NULL,
324
			efipart_cdinfo_add(efipart_handles[i], NULL,
325
			    devpath);
325
			    devpath);
326
			continue;
326
			continue;
327
		}
327
		}
328
328
329
		/* USB or SATA cd without the media. */
329
		/* USB or SATA cd without the media. */
330
		if (blkio->Media->RemovableMedia &&
330
		if (blkio->Media->RemovableMedia &&
331
		    !blkio->Media->MediaPresent) {
331
		    !blkio->Media->MediaPresent) {
332
			efipart_cdinfo_add(efipart_handles[i], NULL,
332
			efipart_cdinfo_add(efipart_handles[i], NULL,
333
			    devpath);
333
			    devpath);
334
		}
334
		}
335
	}
335
	}
336
}
336
}
337
337
338
static int
338
static int
339
efipart_initcd(void)
339
efipart_initcd(void)
340
{
340
{
341
	int rv;
341
	int rv;
342
342
343
	rv = efipart_inithandles();
343
	rv = efipart_inithandles();
344
	if (rv != 0)
344
	if (rv != 0)
345
		return (rv);
345
		return (rv);
346
	STAILQ_INIT(&cdinfo);
346
	STAILQ_INIT(&cdinfo);
347
347
348
	efipart_updatecd();
348
	efipart_updatecd();
349
349
350
	bcache_add_dev(efiblk_pdinfo_count(&cdinfo));
350
	bcache_add_dev(efiblk_pdinfo_count(&cdinfo));
351
	return (0);
351
	return (0);
352
}
352
}
353
353
354
static int
354
static int
355
efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
355
efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
356
{
356
{
357
	EFI_DEVICE_PATH *disk_devpath, *part_devpath;
357
	EFI_DEVICE_PATH *disk_devpath, *part_devpath;
358
	HARDDRIVE_DEVICE_PATH *node;
358
	HARDDRIVE_DEVICE_PATH *node;
359
	int unit;
359
	int unit;
360
	pdinfo_t *hd, *pd, *last;
360
	pdinfo_t *hd, *pd, *last;
361
361
362
	disk_devpath = efi_lookup_devpath(disk_handle);
362
	disk_devpath = efi_lookup_devpath(disk_handle);
363
	part_devpath = efi_lookup_devpath(part_handle);
363
	part_devpath = efi_lookup_devpath(part_handle);
364
	if (disk_devpath == NULL || part_devpath == NULL) {
364
	if (disk_devpath == NULL || part_devpath == NULL) {
365
		return (ENOENT);
365
		return (ENOENT);
366
	}
366
	}
367
	node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath);
367
	node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath);
368
	if (node == NULL)
368
	if (node == NULL)
369
		return (ENOENT);	/* This should not happen. */
369
		return (ENOENT);	/* This should not happen. */
370
370
371
	pd = malloc(sizeof(pdinfo_t));
371
	pd = malloc(sizeof(pdinfo_t));
372
	if (pd == NULL) {
372
	if (pd == NULL) {
373
		printf("Failed to add disk, out of memory\n");
373
		printf("Failed to add disk, out of memory\n");
374
		return (ENOMEM);
374
		return (ENOMEM);
375
	}
375
	}
376
	memset(pd, 0, sizeof(pdinfo_t));
376
	memset(pd, 0, sizeof(pdinfo_t));
377
	STAILQ_INIT(&pd->pd_part);
377
	STAILQ_INIT(&pd->pd_part);
378
378
379
	STAILQ_FOREACH(hd, &hdinfo, pd_link) {
379
	STAILQ_FOREACH(hd, &hdinfo, pd_link) {
380
		if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) {
380
		if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) {
381
			/* Add the partition. */
381
			/* Add the partition. */
382
			pd->pd_handle = part_handle;
382
			pd->pd_handle = part_handle;
383
			pd->pd_unit = node->PartitionNumber;
383
			pd->pd_unit = node->PartitionNumber;
384
			pd->pd_devpath = part_devpath;
384
			pd->pd_devpath = part_devpath;
385
			STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
385
			STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
386
			return (0);
386
			return (0);
387
		}
387
		}
388
	}
388
	}
389
389
390
	last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
390
	last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
391
	if (last != NULL)
391
	if (last != NULL)
392
		unit = last->pd_unit + 1;
392
		unit = last->pd_unit + 1;
393
	else
393
	else
394
		unit = 0;
394
		unit = 0;
395
395
396
	/* Add the disk. */
396
	/* Add the disk. */
397
	hd = pd;
397
	hd = pd;
398
	hd->pd_handle = disk_handle;
398
	hd->pd_handle = disk_handle;
399
	hd->pd_unit = unit;
399
	hd->pd_unit = unit;
400
	hd->pd_devpath = disk_devpath;
400
	hd->pd_devpath = disk_devpath;
401
	STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
401
	STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
402
402
403
	pd = malloc(sizeof(pdinfo_t));
403
	pd = malloc(sizeof(pdinfo_t));
404
	if (pd == NULL) {
404
	if (pd == NULL) {
405
		printf("Failed to add partition, out of memory\n");
405
		printf("Failed to add partition, out of memory\n");
406
		return (ENOMEM);
406
		return (ENOMEM);
407
	}
407
	}
408
	memset(pd, 0, sizeof(pdinfo_t));
408
	memset(pd, 0, sizeof(pdinfo_t));
409
	STAILQ_INIT(&pd->pd_part);
409
	STAILQ_INIT(&pd->pd_part);
410
410
411
	/* Add the partition. */
411
	/* Add the partition. */
412
	pd->pd_handle = part_handle;
412
	pd->pd_handle = part_handle;
413
	pd->pd_unit = node->PartitionNumber;
413
	pd->pd_unit = node->PartitionNumber;
414
	pd->pd_devpath = part_devpath;
414
	pd->pd_devpath = part_devpath;
415
	STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
415
	STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
416
416
417
	return (0);
417
	return (0);
418
}
418
}
419
419
420
/*
420
/*
421
 * The MEDIA_FILEPATH_DP has device name.
421
 * The MEDIA_FILEPATH_DP has device name.
422
 * From U-Boot sources it looks like names are in the form
422
 * From U-Boot sources it looks like names are in the form
423
 * of typeN:M, where type is interface type, N is disk id
423
 * of typeN:M, where type is interface type, N is disk id
424
 * and M is partition id.
424
 * and M is partition id.
425
 */
425
 */
426
static int
426
static int
427
efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
427
efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
428
{
428
{
429
	EFI_DEVICE_PATH *devpath;
429
	EFI_DEVICE_PATH *devpath;
430
	FILEPATH_DEVICE_PATH *node;
430
	FILEPATH_DEVICE_PATH *node;
431
	char *pathname, *p;
431
	char *pathname, *p;
432
	int unit, len;
432
	int unit, len;
433
	pdinfo_t *pd, *last;
433
	pdinfo_t *pd, *last;
434
434
435
	/* First collect and verify all the data */
435
	/* First collect and verify all the data */
436
	if ((devpath = efi_lookup_devpath(disk_handle)) == NULL)
436
	if ((devpath = efi_lookup_devpath(disk_handle)) == NULL)
437
		return (ENOENT);
437
		return (ENOENT);
438
	node = (FILEPATH_DEVICE_PATH *)efi_devpath_last_node(devpath);
438
	node = (FILEPATH_DEVICE_PATH *)efi_devpath_last_node(devpath);
439
	if (node == NULL)
439
	if (node == NULL)
440
		return (ENOENT);	/* This should not happen. */
440
		return (ENOENT);	/* This should not happen. */
441
441
442
	pd = malloc(sizeof(pdinfo_t));
442
	pd = malloc(sizeof(pdinfo_t));
443
	if (pd == NULL) {
443
	if (pd == NULL) {
444
		printf("Failed to add disk, out of memory\n");
444
		printf("Failed to add disk, out of memory\n");
445
		return (ENOMEM);
445
		return (ENOMEM);
446
	}
446
	}
447
	memset(pd, 0, sizeof(pdinfo_t));
447
	memset(pd, 0, sizeof(pdinfo_t));
448
	STAILQ_INIT(&pd->pd_part);
448
	STAILQ_INIT(&pd->pd_part);
449
	last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
449
	last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
450
	if (last != NULL)
450
	if (last != NULL)
451
		unit = last->pd_unit + 1;
451
		unit = last->pd_unit + 1;
452
	else
452
	else
453
		unit = 0;
453
		unit = 0;
454
454
455
	/* FILEPATH_DEVICE_PATH has 0 terminated string */
455
	/* FILEPATH_DEVICE_PATH has 0 terminated string */
456
	for (len = 0; node->PathName[len] != 0; len++)
456
	for (len = 0; node->PathName[len] != 0; len++)
457
		;
457
		;
458
	if ((pathname = malloc(len + 1)) == NULL) {
458
	if ((pathname = malloc(len + 1)) == NULL) {
459
		printf("Failed to add disk, out of memory\n");
459
		printf("Failed to add disk, out of memory\n");
460
		free(pd);
460
		free(pd);
461
		return (ENOMEM);
461
		return (ENOMEM);
462
	}
462
	}
463
	cpy16to8(node->PathName, pathname, len + 1);
463
	cpy16to8(node->PathName, pathname, len + 1);
464
	p = strchr(pathname, ':');
464
	p = strchr(pathname, ':');
465
465
466
	/*
466
	/*
467
	 * Assume we are receiving handles in order, first disk handle,
467
	 * Assume we are receiving handles in order, first disk handle,
468
	 * then partitions for this disk. If this assumption proves
468
	 * then partitions for this disk. If this assumption proves
469
	 * false, this code would need update.
469
	 * false, this code would need update.
470
	 */
470
	 */
471
	if (p == NULL) {	/* no colon, add the disk */
471
	if (p == NULL) {	/* no colon, add the disk */
472
		pd->pd_handle = disk_handle;
472
		pd->pd_handle = disk_handle;
473
		pd->pd_unit = unit;
473
		pd->pd_unit = unit;
474
		pd->pd_devpath = devpath;
474
		pd->pd_devpath = devpath;
475
		STAILQ_INSERT_TAIL(&hdinfo, pd, pd_link);
475
		STAILQ_INSERT_TAIL(&hdinfo, pd, pd_link);
476
		free(pathname);
476
		free(pathname);
477
		return (0);
477
		return (0);
478
	}
478
	}
479
	p++;	/* skip the colon */
479
	p++;	/* skip the colon */
480
	unit = (int)strtol(p, NULL, 0);
480
	unit = (int)strtol(p, NULL, 0);
481
481
482
	/*
482
	/*
483
	 * We should have disk registered, if not, we are receiving
483
	 * We should have disk registered, if not, we are receiving
484
	 * handles out of order, and this code should be reworked
484
	 * handles out of order, and this code should be reworked
485
	 * to create "blank" disk for partition, and to find the
485
	 * to create "blank" disk for partition, and to find the
486
	 * disk based on PathName compares.
486
	 * disk based on PathName compares.
487
	 */
487
	 */
488
	if (last == NULL) {
488
	if (last == NULL) {
489
		printf("BUG: No disk for partition \"%s\"\n", pathname);
489
		printf("BUG: No disk for partition \"%s\"\n", pathname);
490
		free(pathname);
490
		free(pathname);
491
		free(pd);
491
		free(pd);
492
		return (EINVAL);
492
		return (EINVAL);
493
	}
493
	}
494
	/* Add the partition. */
494
	/* Add the partition. */
495
	pd->pd_handle = disk_handle;
495
	pd->pd_handle = disk_handle;
496
	pd->pd_unit = unit;
496
	pd->pd_unit = unit;
497
	pd->pd_devpath = devpath;
497
	pd->pd_devpath = devpath;
498
	STAILQ_INSERT_TAIL(&last->pd_part, pd, pd_link);
498
	STAILQ_INSERT_TAIL(&last->pd_part, pd, pd_link);
499
	free(pathname);
499
	free(pathname);
500
	return (0);
500
	return (0);
501
}
501
}
502
502
503
static void
503
static void
504
efipart_updatehd(void)
504
efipart_updatehd(void)
505
{
505
{
506
	int i, nin;
506
	int i, nin;
507
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
507
	EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
508
	EFI_HANDLE handle;
508
	EFI_HANDLE handle;
509
	EFI_BLOCK_IO *blkio;
509
	EFI_BLOCK_IO *blkio;
510
	EFI_STATUS status;
510
	EFI_STATUS status;
511
511
512
	nin = efipart_nhandles / sizeof (*efipart_handles);
512
	nin = efipart_nhandles / sizeof (*efipart_handles);
513
	for (i = 0; i < nin; i++) {
513
	for (i = 0; i < nin; i++) {
514
		devpath = efi_lookup_devpath(efipart_handles[i]);
514
		devpath = efi_lookup_devpath(efipart_handles[i]);
515
		if (devpath == NULL)
515
		if (devpath == NULL)
516
			continue;
516
			continue;
517
517
518
		if ((node = efi_devpath_last_node(devpath)) == NULL)
518
		if ((node = efi_devpath_last_node(devpath)) == NULL)
519
			continue;
519
			continue;
520
		if (efipart_floppy(node) != NULL)
520
		if (efipart_floppy(node) != NULL)
521
			continue;
521
			continue;
522
522
523
		status = BS->HandleProtocol(efipart_handles[i],
523
		status = BS->HandleProtocol(efipart_handles[i],
524
		    &blkio_guid, (void **)&blkio);
524
		    &blkio_guid, (void **)&blkio);
525
		if (EFI_ERROR(status))
525
		if (EFI_ERROR(status))
526
			continue;
526
			continue;
527
527
528
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
528
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
529
		    DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) {
529
		    DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) {
530
			devpathcpy = efi_devpath_trim(devpath);
530
			devpathcpy = efi_devpath_trim(devpath);
531
			if (devpathcpy == NULL)
531
			if (devpathcpy == NULL)
532
				continue;
532
				continue;
533
			tmpdevpath = devpathcpy;
533
			tmpdevpath = devpathcpy;
534
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
534
			status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
535
			    &handle);
535
			    &handle);
536
			free(devpathcpy);
536
			free(devpathcpy);
537
			if (EFI_ERROR(status))
537
			if (EFI_ERROR(status))
538
				continue;
538
				continue;
539
			/*
539
			/*
540
			 * We do not support nested partitions.
540
			 * We do not support nested partitions.
541
			 */
541
			 */
542
			devpathcpy = efi_lookup_devpath(handle);
542
			devpathcpy = efi_lookup_devpath(handle);
543
			if (devpathcpy == NULL)
543
			if (devpathcpy == NULL)
544
				continue;
544
				continue;
545
			if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
545
			if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
546
				continue;
546
				continue;
547
			if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
547
			if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
548
			    DevicePathSubType(node) == MEDIA_HARDDRIVE_DP)
548
			    DevicePathSubType(node) == MEDIA_HARDDRIVE_DP)
549
				continue;
549
				continue;
550
			efipart_hdinfo_add(handle, efipart_handles[i]);
550
			efipart_hdinfo_add(handle, efipart_handles[i]);
551
			continue;
551
			continue;
552
		}
552
		}
553
553
554
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
554
		if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
555
		    DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
555
		    DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
556
			efipart_hdinfo_add_filepath(efipart_handles[i]);
556
			efipart_hdinfo_add_filepath(efipart_handles[i]);
557
			continue;
557
			continue;
558
		}
558
		}
559
	}
559
	}
560
}
560
}
561
561
562
static int
562
static int
563
efipart_inithd(void)
563
efipart_inithd(void)
564
{
564
{
565
	int rv;
565
	int rv;
566
566
567
	rv = efipart_inithandles();
567
	rv = efipart_inithandles();
568
	if (rv != 0)
568
	if (rv != 0)
569
		return (rv);
569
		return (rv);
570
	STAILQ_INIT(&hdinfo);
570
	STAILQ_INIT(&hdinfo);
571
571
572
	efipart_updatehd();
572
	efipart_updatehd();
573
573
574
	bcache_add_dev(efiblk_pdinfo_count(&hdinfo));
574
	bcache_add_dev(efiblk_pdinfo_count(&hdinfo));
575
	return (0);
575
	return (0);
576
}
576
}
577
577
578
static int
578
static int
579
efipart_print_common(struct devsw *dev, pdinfo_list_t *pdlist, int verbose)
579
efipart_print_common(struct devsw *dev, pdinfo_list_t *pdlist, int verbose)
580
{
580
{
581
	int ret = 0;
581
	int ret = 0;
582
	EFI_BLOCK_IO *blkio;
582
	EFI_BLOCK_IO *blkio;
583
	EFI_STATUS status;
583
	EFI_STATUS status;
584
	EFI_HANDLE h;
584
	EFI_HANDLE h;
585
	pdinfo_t *pd;
585
	pdinfo_t *pd;
586
	CHAR16 *text;
586
	CHAR16 *text;
587
	struct disk_devdesc pd_dev;
587
	struct disk_devdesc pd_dev;
588
	char line[80];
588
	char line[80];
589
589
590
	if (STAILQ_EMPTY(pdlist))
590
	if (STAILQ_EMPTY(pdlist))
591
		return (0);
591
		return (0);
592
592
593
	printf("%s devices:", dev->dv_name);
593
	printf("%s devices:", dev->dv_name);
594
	if ((ret = pager_output("\n")) != 0)
594
	if ((ret = pager_output("\n")) != 0)
595
		return (ret);
595
		return (ret);
596
596
597
	STAILQ_FOREACH(pd, pdlist, pd_link) {
597
	STAILQ_FOREACH(pd, pdlist, pd_link) {
598
		h = pd->pd_handle;
598
		h = pd->pd_handle;
599
		if (verbose) {	/* Output the device path. */
599
		if (verbose) {	/* Output the device path. */
600
			text = efi_devpath_name(efi_lookup_devpath(h));
600
			text = efi_devpath_name(efi_lookup_devpath(h));
601
			if (text != NULL) {
601
			if (text != NULL) {
602
				printf("  %S", text);
602
				printf("  %S", text);
603
				efi_free_devpath_name(text);
603
				efi_free_devpath_name(text);
604
				if ((ret = pager_output("\n")) != 0)
604
				if ((ret = pager_output("\n")) != 0)
605
					break;
605
					break;
606
			}
606
			}
607
		}
607
		}
608
		snprintf(line, sizeof(line),
608
		snprintf(line, sizeof(line),
609
		    "    %s%d", dev->dv_name, pd->pd_unit);
609
		    "    %s%d", dev->dv_name, pd->pd_unit);
610
		printf("%s:", line);
610
		printf("%s:", line);
611
		status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
611
		status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
612
		if (!EFI_ERROR(status)) {
612
		if (!EFI_ERROR(status)) {
613
			printf("    %llu",
613
			printf("    %llu",
614
			    blkio->Media->LastBlock == 0? 0:
614
			    blkio->Media->LastBlock == 0? 0:
615
			    (unsigned long long) (blkio->Media->LastBlock + 1));
615
			    (unsigned long long) (blkio->Media->LastBlock + 1));
616
			if (blkio->Media->LastBlock != 0) {
616
			if (blkio->Media->LastBlock != 0) {
617
				printf(" X %u", blkio->Media->BlockSize);
617
				printf(" X %u", blkio->Media->BlockSize);
618
			}
618
			}
619
			printf(" blocks");
619
			printf(" blocks");
620
			if (blkio->Media->MediaPresent) {
620
			if (blkio->Media->MediaPresent) {
621
				if (blkio->Media->RemovableMedia)
621
				if (blkio->Media->RemovableMedia)
622
					printf(" (removable)");
622
					printf(" (removable)");
623
			} else
623
			} else
624
				printf(" (no media)");
624
				printf(" (no media)");
625
			if ((ret = pager_output("\n")) != 0)
625
			if ((ret = pager_output("\n")) != 0)
626
				break;
626
				break;
627
			if (!blkio->Media->MediaPresent)
627
			if (!blkio->Media->MediaPresent)
628
				continue;
628
				continue;
629
629
630
			pd->pd_blkio = blkio;
630
			pd->pd_blkio = blkio;
631
			pd_dev.d_dev = dev;
631
			pd_dev.d_dev = dev;
632
			pd_dev.d_unit = pd->pd_unit;
632
			pd_dev.d_unit = pd->pd_unit;
633
			pd_dev.d_slice = -1;
633
			pd_dev.d_slice = -1;
634
			pd_dev.d_partition = -1;
634
			pd_dev.d_partition = -1;
635
			pd_dev.d_opendata = blkio;
635
			pd_dev.d_opendata = blkio;
636
			ret = disk_open(&pd_dev, blkio->Media->BlockSize *
636
			ret = disk_open(&pd_dev, blkio->Media->BlockSize *
637
			    (blkio->Media->LastBlock + 1),
637
			    (blkio->Media->LastBlock + 1),
638
			    blkio->Media->BlockSize);
638
			    blkio->Media->BlockSize);
639
			if (ret == 0) {
639
			if (ret == 0) {
640
				ret = disk_print(&pd_dev, line, verbose);
640
				ret = disk_print(&pd_dev, line, verbose);
641
				disk_close(&pd_dev);
641
				disk_close(&pd_dev);
642
				if (ret != 0)
642
				if (ret != 0)
643
					return (ret);
643
					return (ret);
644
			} else {
644
			} else {
645
				/* Do not fail from disk_open() */
645
				/* Do not fail from disk_open() */
646
				ret = 0;
646
				ret = 0;
647
			}
647
			}
648
		} else {
648
		} else {
649
			if ((ret = pager_output("\n")) != 0)
649
			if ((ret = pager_output("\n")) != 0)
650
				break;
650
				break;
651
		}
651
		}
652
	}
652
	}
653
	return (ret);
653
	return (ret);
654
}
654
}
655
655
656
static int
656
static int
657
efipart_printfd(int verbose)
657
efipart_printfd(int verbose)
658
{
658
{
659
	return (efipart_print_common(&efipart_fddev, &fdinfo, verbose));
659
	return (efipart_print_common(&efipart_fddev, &fdinfo, verbose));
660
}
660
}
661
661
662
static int
662
static int
663
efipart_printcd(int verbose)
663
efipart_printcd(int verbose)
664
{
664
{
665
	return (efipart_print_common(&efipart_cddev, &cdinfo, verbose));
665
	return (efipart_print_common(&efipart_cddev, &cdinfo, verbose));
666
}
666
}
667
667
668
static int
668
static int
669
efipart_printhd(int verbose)
669
efipart_printhd(int verbose)
670
{
670
{
671
	return (efipart_print_common(&efipart_hddev, &hdinfo, verbose));
671
	return (efipart_print_common(&efipart_hddev, &hdinfo, verbose));
672
}
672
}
673
673
674
pdinfo_list_t *
674
pdinfo_list_t *
675
efiblk_get_pdinfo_list(struct devsw *dev)
675
efiblk_get_pdinfo_list(struct devsw *dev)
676
{
676
{
677
	if (dev->dv_type == DEVT_DISK)
677
	if (dev->dv_type == DEVT_DISK)
678
		return (&hdinfo);
678
		return (&hdinfo);
679
	if (dev->dv_type == DEVT_CD)
679
	if (dev->dv_type == DEVT_CD)
680
		return (&cdinfo);
680
		return (&cdinfo);
681
	if (dev->dv_type == DEVT_FD)
681
	if (dev->dv_type == DEVT_FD)
682
		return (&fdinfo);
682
		return (&fdinfo);
683
	return (NULL);
683
	return (NULL);
684
}
684
}
685
685
686
static int
686
static int
687
efipart_open(struct open_file *f, ...)
687
efipart_open(struct open_file *f, ...)
688
{
688
{
689
	va_list args;
689
	va_list args;
690
	struct disk_devdesc *dev;
690
	struct disk_devdesc *dev;
691
	pdinfo_list_t *pdi;
691
	pdinfo_list_t *pdi;
692
	pdinfo_t *pd;
692
	pdinfo_t *pd;
693
	EFI_BLOCK_IO *blkio;
693
	EFI_BLOCK_IO *blkio;
694
	EFI_STATUS status;
694
	EFI_STATUS status;
695
695
696
	va_start(args, f);
696
	va_start(args, f);
697
	dev = va_arg(args, struct disk_devdesc*);
697
	dev = va_arg(args, struct disk_devdesc*);
698
	va_end(args);
698
	va_end(args);
699
	if (dev == NULL)
699
	if (dev == NULL)
700
		return (EINVAL);
700
		return (EINVAL);
701
701
702
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
702
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
703
	if (pdi == NULL)
703
	if (pdi == NULL)
704
		return (EINVAL);
704
		return (EINVAL);
705
705
706
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
706
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
707
	if (pd == NULL)
707
	if (pd == NULL)
708
		return (EIO);
708
		return (EIO);
709
709
710
	if (pd->pd_blkio == NULL) {
710
	if (pd->pd_blkio == NULL) {
711
		status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
711
		status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
712
		    (void **)&pd->pd_blkio);
712
		    (void **)&pd->pd_blkio);
713
		if (EFI_ERROR(status))
713
		if (EFI_ERROR(status))
714
			return (efi_status_to_errno(status));
714
			return (efi_status_to_errno(status));
715
	}
715
	}
716
716
717
	blkio = pd->pd_blkio;
717
	blkio = pd->pd_blkio;
718
	if (!blkio->Media->MediaPresent)
718
	if (!blkio->Media->MediaPresent)
719
		return (EAGAIN);
719
		return (EAGAIN);
720
720
721
	pd->pd_open++;
721
	pd->pd_open++;
722
	if (pd->pd_bcache == NULL)
722
	if (pd->pd_bcache == NULL)
723
		pd->pd_bcache = bcache_allocate();
723
		pd->pd_bcache = bcache_allocate();
724
724
725
	if (dev->d_dev->dv_type == DEVT_DISK) {
725
	if (dev->d_dev->dv_type == DEVT_DISK) {
726
		return (disk_open(dev,
726
		return (disk_open(dev,
727
		    blkio->Media->BlockSize * (blkio->Media->LastBlock + 1),
727
		    blkio->Media->BlockSize * (blkio->Media->LastBlock + 1),
728
		    blkio->Media->BlockSize));
728
		    blkio->Media->BlockSize));
729
	}
729
	}
730
	return (0);
730
	return (0);
731
}
731
}
732
732
733
static int
733
static int
734
efipart_close(struct open_file *f)
734
efipart_close(struct open_file *f)
735
{
735
{
736
	struct disk_devdesc *dev;
736
	struct disk_devdesc *dev;
737
	pdinfo_list_t *pdi;
737
	pdinfo_list_t *pdi;
738
	pdinfo_t *pd;
738
	pdinfo_t *pd;
739
739
740
	dev = (struct disk_devdesc *)(f->f_devdata);
740
	dev = (struct disk_devdesc *)(f->f_devdata);
741
	if (dev == NULL)
741
	if (dev == NULL)
742
		return (EINVAL);
742
		return (EINVAL);
743
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
743
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
744
	if (pdi == NULL)
744
	if (pdi == NULL)
745
		return (EINVAL);
745
		return (EINVAL);
746
746
747
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
747
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
748
	if (pd == NULL)
748
	if (pd == NULL)
749
		return (EINVAL);
749
		return (EINVAL);
750
750
751
	pd->pd_open--;
751
	pd->pd_open--;
752
	if (pd->pd_open == 0) {
752
	if (pd->pd_open == 0) {
753
		pd->pd_blkio = NULL;
753
		pd->pd_blkio = NULL;
754
		bcache_free(pd->pd_bcache);
754
		bcache_free(pd->pd_bcache);
755
		pd->pd_bcache = NULL;
755
		pd->pd_bcache = NULL;
756
	}
756
	}
757
	if (dev->d_dev->dv_type == DEVT_DISK)
757
	if (dev->d_dev->dv_type == DEVT_DISK)
758
		return (disk_close(dev));
758
		return (disk_close(dev));
759
	return (0);
759
	return (0);
760
}
760
}
761
761
762
static int
762
static int
763
efipart_ioctl(struct open_file *f, u_long cmd, void *data)
763
efipart_ioctl(struct open_file *f, u_long cmd, void *data)
764
{
764
{
765
	struct disk_devdesc *dev;
765
	struct disk_devdesc *dev;
766
	pdinfo_list_t *pdi;
766
	pdinfo_list_t *pdi;
767
	pdinfo_t *pd;
767
	pdinfo_t *pd;
768
	int rc;
768
	int rc;
769
769
770
	dev = (struct disk_devdesc *)(f->f_devdata);
770
	dev = (struct disk_devdesc *)(f->f_devdata);
771
	if (dev == NULL)
771
	if (dev == NULL)
772
		return (EINVAL);
772
		return (EINVAL);
773
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
773
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
774
	if (pdi == NULL)
774
	if (pdi == NULL)
775
		return (EINVAL);
775
		return (EINVAL);
776
776
777
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
777
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
778
	if (pd == NULL)
778
	if (pd == NULL)
779
		return (EINVAL);
779
		return (EINVAL);
780
780
781
	if (dev->d_dev->dv_type == DEVT_DISK) {
781
	if (dev->d_dev->dv_type == DEVT_DISK) {
782
		rc = disk_ioctl(dev, cmd, data);
782
		rc = disk_ioctl(dev, cmd, data);
783
		if (rc != ENOTTY)
783
		if (rc != ENOTTY)
784
			return (rc);
784
			return (rc);
785
	}
785
	}
786
786
787
	switch (cmd) {
787
	switch (cmd) {
788
	case DIOCGSECTORSIZE:
788
	case DIOCGSECTORSIZE:
789
		*(u_int *)data = pd->pd_blkio->Media->BlockSize;
789
		*(u_int *)data = pd->pd_blkio->Media->BlockSize;
790
		break;
790
		break;
791
	case DIOCGMEDIASIZE:
791
	case DIOCGMEDIASIZE:
792
		*(uint64_t *)data = pd->pd_blkio->Media->BlockSize *
792
		*(uint64_t *)data = pd->pd_blkio->Media->BlockSize *
793
		    (pd->pd_blkio->Media->LastBlock + 1);
793
		    (pd->pd_blkio->Media->LastBlock + 1);
794
		break;
794
		break;
795
	default:
795
	default:
796
		return (ENOTTY);
796
		return (ENOTTY);
797
	}
797
	}
798
798
799
	return (0);
799
	return (0);
800
}
800
}
801
801
802
/*
802
/*
803
 * efipart_readwrite()
803
 * efipart_readwrite()
804
 * Internal equivalent of efipart_strategy(), which operates on the
804
 * Internal equivalent of efipart_strategy(), which operates on the
805
 * media-native block size. This function expects all I/O requests
805
 * media-native block size. This function expects all I/O requests
806
 * to be within the media size and returns an error if such is not
806
 * to be within the media size and returns an error if such is not
807
 * the case.
807
 * the case.
808
 */
808
 */
809
static int
809
static int
810
efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks,
810
efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks,
811
    char *buf)
811
    char *buf)
812
{
812
{
813
	EFI_STATUS status;
813
	EFI_STATUS status;
814
814
815
	if (blkio == NULL)
815
	if (blkio == NULL)
816
		return (ENXIO);
816
		return (ENXIO);
817
	if (blk < 0 || blk > blkio->Media->LastBlock)
817
	if (blk < 0 || blk > blkio->Media->LastBlock)
818
		return (EIO);
818
		return (EIO);
819
	if ((blk + nblks - 1) > blkio->Media->LastBlock)
819
	if ((blk + nblks - 1) > blkio->Media->LastBlock)
820
		return (EIO);
820
		return (EIO);
821
821
822
	switch (rw & F_MASK) {
822
	switch (rw & F_MASK) {
823
	case F_READ:
823
	case F_READ:
824
		status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk,
824
		status = blkio->ReadBlocks(blkio, blkio->Media->MediaId, blk,
825
		    nblks * blkio->Media->BlockSize, buf);
825
		    nblks * blkio->Media->BlockSize, buf);
826
		break;
826
		break;
827
	case F_WRITE:
827
	case F_WRITE:
828
		if (blkio->Media->ReadOnly)
828
		if (blkio->Media->ReadOnly)
829
			return (EROFS);
829
			return (EROFS);
830
		status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk,
830
		status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk,
831
		    nblks * blkio->Media->BlockSize, buf);
831
		    nblks * blkio->Media->BlockSize, buf);
832
		break;
832
		break;
833
	default:
833
	default:
834
		return (ENOSYS);
834
		return (ENOSYS);
835
	}
835
	}
836
836
837
	if (EFI_ERROR(status)) {
837
	if (EFI_ERROR(status)) {
838
		printf("%s: rw=%d, blk=%ju size=%ju status=%lu\n", __func__, rw,
838
		printf("%s: rw=%d, blk=%ju size=%ju status=%lu\n", __func__, rw,
839
		    blk, nblks, EFI_ERROR_CODE(status));
839
		    blk, nblks, EFI_ERROR_CODE(status));
840
	}
840
	}
841
	return (efi_status_to_errno(status));
841
	return (efi_status_to_errno(status));
842
}
842
}
843
843
844
static int
844
static int
845
efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size,
845
efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size,
846
    char *buf, size_t *rsize)
846
    char *buf, size_t *rsize)
847
{
847
{
848
	struct bcache_devdata bcd;
848
	struct bcache_devdata bcd;
849
	struct disk_devdesc *dev;
849
	struct disk_devdesc *dev;
850
	pdinfo_list_t *pdi;
850
	pdinfo_list_t *pdi;
851
	pdinfo_t *pd;
851
	pdinfo_t *pd;
852
852
853
	dev = (struct disk_devdesc *)devdata;
853
	dev = (struct disk_devdesc *)devdata;
854
	if (dev == NULL)
854
	if (dev == NULL)
855
		return (EINVAL);
855
		return (EINVAL);
856
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
856
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
857
	if (pdi == NULL)
857
	if (pdi == NULL)
858
		return (EINVAL);
858
		return (EINVAL);
859
859
860
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
860
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
861
	if (pd == NULL)
861
	if (pd == NULL)
862
		return (EINVAL);
862
		return (EINVAL);
863
863
864
	if (pd->pd_blkio->Media->RemovableMedia &&
864
	if (pd->pd_blkio->Media->RemovableMedia &&
865
	    !pd->pd_blkio->Media->MediaPresent)
865
	    !pd->pd_blkio->Media->MediaPresent)
866
		return (EIO);
866
		return (EIO);
867
867
868
	bcd.dv_strategy = efipart_realstrategy;
868
	bcd.dv_strategy = efipart_realstrategy;
869
	bcd.dv_devdata = devdata;
869
	bcd.dv_devdata = devdata;
870
	bcd.dv_cache = pd->pd_bcache;
870
	bcd.dv_cache = pd->pd_bcache;
871
871
872
	if (dev->d_dev->dv_type == DEVT_DISK) {
872
	if (dev->d_dev->dv_type == DEVT_DISK) {
873
		return (bcache_strategy(&bcd, rw, blk + dev->d_offset,
873
		return (bcache_strategy(&bcd, rw, blk + dev->d_offset,
874
		    size, buf, rsize));
874
		    size, buf, rsize));
875
	}
875
	}
876
	return (bcache_strategy(&bcd, rw, blk, size, buf, rsize));
876
	return (bcache_strategy(&bcd, rw, blk, size, buf, rsize));
877
}
877
}
878
878
879
static int
879
static int
880
efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size,
880
efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size,
881
    char *buf, size_t *rsize)
881
    char *buf, size_t *rsize)
882
{
882
{
883
	struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
883
	struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
884
	pdinfo_list_t *pdi;
884
	pdinfo_list_t *pdi;
885
	pdinfo_t *pd;
885
	pdinfo_t *pd;
886
	EFI_BLOCK_IO *blkio;
886
	EFI_BLOCK_IO *blkio;
887
	uint64_t off, disk_blocks, d_offset = 0;
887
	uint64_t off, disk_blocks, d_offset = 0;
888
	char *blkbuf;
888
	char *blkbuf;
889
	size_t blkoff, blksz;
889
	size_t blkoff, blksz;
890
	int error;
890
	int error;
891
891
892
	if (dev == NULL || blk < 0)
892
	if (dev == NULL || blk < 0)
893
		return (EINVAL);
893
		return (EINVAL);
894
894
895
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
895
	pdi = efiblk_get_pdinfo_list(dev->d_dev);
896
	if (pdi == NULL)
896
	if (pdi == NULL)
897
		return (EINVAL);
897
		return (EINVAL);
898
898
899
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
899
	pd = efiblk_get_pdinfo(pdi, dev->d_unit);
900
	if (pd == NULL)
900
	if (pd == NULL)
901
		return (EINVAL);
901
		return (EINVAL);
902
902
903
	blkio = pd->pd_blkio;
903
	blkio = pd->pd_blkio;
904
	if (blkio == NULL)
904
	if (blkio == NULL)
905
		return (ENXIO);
905
		return (ENXIO);
906
906
907
	if (size == 0 || (size % 512) != 0)
907
	if (size == 0 || (size % 512) != 0)
908
		return (EIO);
908
		return (EIO);
909
909
910
	off = blk * 512;
910
	off = blk * 512;
911
	/*
911
	/*
912
	 * Get disk blocks, this value is either for whole disk or for
912
	 * Get disk blocks, this value is either for whole disk or for
913
	 * partition.
913
	 * partition.
914
	 */
914
	 */
915
	disk_blocks = 0;
915
	disk_blocks = 0;
916
	if (dev->d_dev->dv_type == DEVT_DISK) {
916
	if (dev->d_dev->dv_type == DEVT_DISK) {
917
		if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
917
		if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
918
			/* DIOCGMEDIASIZE does return bytes. */
918
			/* DIOCGMEDIASIZE does return bytes. */
919
			disk_blocks /= blkio->Media->BlockSize;
919
			disk_blocks /= blkio->Media->BlockSize;
920
		}
920
		}
921
		d_offset = dev->d_offset;
921
		d_offset = dev->d_offset;
922
	}
922
	}
923
	if (disk_blocks == 0)
923
	if (disk_blocks == 0)
924
		disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
924
		disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
925
925
926
	/* make sure we don't read past disk end */
926
	/* make sure we don't read past disk end */
927
	if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) {
927
	if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) {
928
		size = d_offset + disk_blocks - off / blkio->Media->BlockSize;
928
                size_t diskend = d_offset + disk_blocks;
929
                size_t readstart = off / blkio->Media->BlockSize;
930
931
                if (diskend <= readstart) {
932
                        *rsize = 0;
933
934
                        return (0);
935
                }
936
		size = diskend - readstart;
929
		size = size * blkio->Media->BlockSize;
937
		size = size * blkio->Media->BlockSize;
930
	}
938
	}
931
939
932
	if (rsize != NULL)
940
	if (rsize != NULL)
933
		*rsize = size;
941
		*rsize = size;
934
942
935
	if ((size % blkio->Media->BlockSize == 0) &&
943
	if ((size % blkio->Media->BlockSize == 0) &&
936
	    (off % blkio->Media->BlockSize == 0))
944
	    (off % blkio->Media->BlockSize == 0))
937
		return (efipart_readwrite(blkio, rw,
945
		return (efipart_readwrite(blkio, rw,
938
		    off / blkio->Media->BlockSize,
946
		    off / blkio->Media->BlockSize,
939
		    size / blkio->Media->BlockSize, buf));
947
		    size / blkio->Media->BlockSize, buf));
940
948
941
	/*
949
	/*
942
	 * The block size of the media is not a multiple of I/O.
950
	 * The block size of the media is not a multiple of I/O.
943
	 */
951
	 */
944
	blkbuf = malloc(blkio->Media->BlockSize);
952
	blkbuf = malloc(blkio->Media->BlockSize);
945
	if (blkbuf == NULL)
953
	if (blkbuf == NULL)
946
		return (ENOMEM);
954
		return (ENOMEM);
947
955
948
	error = 0;
956
	error = 0;
949
	blk = off / blkio->Media->BlockSize;
957
	blk = off / blkio->Media->BlockSize;
950
	blkoff = off % blkio->Media->BlockSize;
958
	blkoff = off % blkio->Media->BlockSize;
951
	blksz = blkio->Media->BlockSize - blkoff;
959
	blksz = blkio->Media->BlockSize - blkoff;
952
	while (size > 0) {
960
	while (size > 0) {
953
		error = efipart_readwrite(blkio, rw, blk, 1, blkbuf);
961
		error = efipart_readwrite(blkio, rw, blk, 1, blkbuf);
954
		if (error)
962
		if (error)
955
			break;
963
			break;
956
		if (size < blksz)
964
		if (size < blksz)
957
			blksz = size;
965
			blksz = size;
958
		bcopy(blkbuf + blkoff, buf, blksz);
966
		bcopy(blkbuf + blkoff, buf, blksz);
959
		buf += blksz;
967
		buf += blksz;
960
		size -= blksz;
968
		size -= blksz;
961
		blk++;
969
		blk++;
962
		blkoff = 0;
970
		blkoff = 0;
963
		blksz = blkio->Media->BlockSize;
971
		blksz = blkio->Media->BlockSize;
964
	}
972
	}
965
973
966
	free(blkbuf);
974
	free(blkbuf);
967
	return (error);
975
	return (error);
968
}
976
}

Return to bug 219000