View | Details | Raw Unified | Return to bug 207940 | Differences between
and this patch

Collapse All | Expand All

(-)stand/efi/boot1/boot1.c (-6 / +1 lines)
Lines 320-331 efi_panic(EFI_STATUS s, const char *fmt, ...) Link Here
320
	va_end(ap);
308
	va_end(ap);
321
	printf("\n");
309
	printf("\n");
322
310
323
	efi_exit(s);
311
	BS->Exit(IH, s, 0, NULL);
324
}
325
326
int getchar(void)
327
{
328
	return (-1);
329
}
312
}
330
313
331
void
314
void
(-)stand/efi/boot1/proto.c (-6 / +392 lines)
Lines 45-51 Link Here
45
	"better"
45
	"better"
46
};
46
};
47
47
48
/* quick and dirty work for boot partition menu */
49
50
#define	NUM_DEV_LIST	35
51
#define	SELECT_TIMEOUT	10
52
53
typedef struct {
54
	const boot_module_t	*modp;
55
	dev_info_t		*devinfop;
56
} moddev_t;
57
58
static moddev_t dev_list[NUM_DEV_LIST];
59
60
static EFI_STATUS
61
load_loader(const boot_module_t **modp, dev_info_t **devinfop, void **bufp,
62
    size_t *bufsize, int preferred);
63
64
static char *
65
humanize_number_kmgt(UINT64 size) {
66
	static char buf2[6];
67
	UINT64 size0;
68
69
	if (size < 1024)
70
		sprintf(buf2, "%luB", size);
71
	else if (size0 = (size*10+512)/1024, size0 < 100)
72
		sprintf(buf2, "%lu.%luK", size0 / 10, size0 % 10);
73
	else if (size0 = (size+512)/1024, size0 < 1024)
74
		sprintf(buf2, "%luK", size0);
75
	else if (size0 = (size*10/1024+512)/1024, size0 < 100)
76
		sprintf(buf2, "%lu.%luM", size0 / 10, size0 % 10);
77
	else if (size0 = (size/1024+512)/1024, size0 < 1024)
78
		sprintf(buf2, "%luM", size0);
79
	else if (size0 = (size*10/1024/1024+512)/1024, size0 < 100)
80
		sprintf(buf2, "%lu.%luG", size0 / 10, size0 % 10);
81
	else if (size0 = (size/1024/1024+512)/1024, size0 < 1024)
82
		sprintf(buf2, "%luG", size0);
83
	else if (size0 = (size*10/1024/1024/1024+512)/1024, size0 < 100)
84
		sprintf(buf2, "%lu.%luT", size0 / 10, size0 % 10);
85
	else
86
		sprintf(buf2, "%luT", (size/1024/1024/1024+512)/1024);
87
	return(buf2);
88
}
89
90
static char
91
idx2char(int i)
92
{
93
	return (i<10 ? '0'+i : 'a'+i-10);
94
}
95
96
static int
97
char2idx(char c)
98
{
99
	return ((c >= '0' && c <= '9') ? c - '0' :
100
	    (c >= 'A' && c <= 'Z') ? c - 'A' + 10 :
101
	    (c >= 'a' && c <= 'z') ? c - 'a' + 10 :
102
	    -1 );
103
}
104
105
static void
106
move_to_tol()
107
{
108
	SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
109
	int x,y;
110
111
	conout = ST->ConOut;
112
	x = conout->Mode->CursorColumn;
113
	y = conout->Mode->CursorRow;
114
	conout->SetCursorPosition(conout, 0, y);
115
}
116
117
int
118
getchar(void)
119
{
120
	EFI_INPUT_KEY key;
121
	EFI_STATUS status;
122
	UINTN junk;
123
124
	/* Try to read a key stroke. We wait for one if none is pending. */
125
	status = ST->ConIn->ReadKeyStroke(ST->ConIn, &key);
126
	if (status == EFI_NOT_READY) {
127
		BS->WaitForEvent(1, &ST->ConIn->WaitForKey, &junk);
128
		status = ST->ConIn->ReadKeyStroke(ST->ConIn, &key);
129
	}
130
	switch (key.ScanCode) {
131
	case 0x17: /* ESC */
132
		return (0x1b);  /* esc */
133
	}
134
135
	/* this can return  */
136
	return (key.UnicodeChar);
137
}
138
48
/*
139
/*
140
 * Output of EFI_DEVICE_PATH_TO_TEXT_PROTOCOL is not easy to read.
141
 " I hope this looks better.
142
 */
143
static int
144
mediapath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
145
{
146
	switch (devpath->Type) {
147
	case MEDIA_DEVICE_PATH:
148
		switch (devpath->SubType) {
149
		case MEDIA_CDROM_DP: {
150
			CDROM_DEVICE_PATH *cdrom;
151
152
			cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
153
			return snprintf(buf, size, "cdrom(%x)",
154
			    cdrom->BootEntry);
155
		}
156
		case MEDIA_HARDDRIVE_DP: {
157
			HARDDRIVE_DEVICE_PATH *hd;
158
159
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
160
			return snprintf(buf, size, "hd(p%d) (%s)",
161
			    hd->PartitionNumber,
162
			    humanize_number_kmgt(hd->PartitionSize * 512));
163
		}
164
		default:
165
			return snprintf(buf, size, "media(0x%02x)",
166
			    devpath->SubType);
167
		}
168
	}
169
170
	return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
171
	    devpath->SubType);
172
}
173
174
static int
175
messagingpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
176
{
177
	size_t pos = 0;
178
179
	if (IsDevicePathEnd(devpath))
180
		return (-1);
181
	while (!IsDevicePathEnd(NextDevicePathNode(devpath))) {
182
		if (pos >= size)
183
			break;
184
		switch (devpath->Type) {
185
		case MESSAGING_DEVICE_PATH: {
186
			switch (devpath->SubType) {
187
			case MSG_ATAPI_DP: {
188
				ATAPI_DEVICE_PATH *pata;
189
				char prisec[4], masslv[4];
190
191
				pata = (ATAPI_DEVICE_PATH *)(void *)devpath;
192
				if (0 == pata->PrimarySecondary)
193
				    snprintf(prisec, 4, "Pri");
194
				else
195
				    snprintf(prisec, 4, "Sec");
196
				if (0 == pata->SlaveMaster)
197
				    snprintf(masslv, 4, "Mas");
198
				else
199
				    snprintf(masslv, 4, "Slv");
200
				pos += (size_t)snprintf(buf + pos, size - pos,
201
				    "PATA(%s%s)",
202
				    prisec,
203
				    masslv);
204
				break;
205
			}
206
			case MSG_SCSI_DP: {
207
				SCSI_DEVICE_PATH *scsi;
208
209
				scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
210
				pos += (size_t)snprintf(buf + pos, size - pos,
211
				    "SCSI(%2d)    ",
212
				    scsi->Pun);
213
				break;
214
			}
215
			case MSG_SATA_DP: {
216
				SATA_DEVICE_PATH *sata;
217
218
				sata = (SATA_DEVICE_PATH *)(void *)devpath;
219
				pos += (size_t)snprintf(buf + pos, size - pos,
220
				    "SATA(%d)     ",
221
				    sata->HBAPortNumber);
222
				break;
223
			}
224
			case MSG_USB_DP: {
225
				USB_DEVICE_PATH *usb;
226
227
				usb = (USB_DEVICE_PATH *)(void *)devpath;
228
				pos += (size_t)snprintf(buf + pos, size - pos,
229
				    "USB(P%02xI%02x) ",
230
				    usb->ParentPortNumber,
231
				    usb->InterfaceNumber);
232
				break;
233
			}
234
			default:
235
				pos += (size_t)snprintf(buf + pos, size - pos,
236
				    "drive(%02x)   ",
237
				    devpath->SubType);
238
			}
239
		}
240
		}
241
		devpath = NextDevicePathNode(devpath);
242
	}
243
	if (pos > size) return (size); else return (pos);
244
}
245
246
/*
247
 * mediapath_str is convenience method which returns the text description of
248
 * mediapath using a static buffer, so it isn't thread safe!
249
 */
250
static char *
251
mediapath_str(EFI_DEVICE_PATH *devpath)
252
{
253
	static char buf[256];
254
255
	mediapath_node_str(buf, sizeof(buf), devpath);
256
257
	return buf;
258
}
259
260
static char *
261
messagingpath_str(EFI_DEVICE_PATH *devpath)
262
{
263
	static char buf[256];
264
265
	messagingpath_node_str(buf, sizeof(buf), devpath);
266
267
	return buf;
268
}
269
270
static int
271
list_devices(void)
272
{
273
	UINTN i, j;
274
	dev_info_t *dev;
275
	const boot_module_t *mod;
276
277
	j = 0;
278
	for (i = 0; i < num_boot_modules; i++) {
279
		if (boot_modules[i] == NULL)
280
			continue;
281
		mod = boot_modules[i];
282
		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
283
			dev_list[j].devinfop = dev;
284
			dev_list[j].modp = mod;
285
			j++;
286
			if (j >= NUM_DEV_LIST)
287
			    break;
288
		}
289
	}
290
291
	return (j);
292
}
293
294
295
static int
296
get_sel(int ndevs,int time_left)
297
{
298
	int i;
299
	int c, n;
300
	EFI_STATUS status;
301
	EFI_EVENT timer;
302
	EFI_EVENT events[2];
303
	EFI_DEVICE_PATH *mediapath;
304
	UINTN idx;
305
306
	status = BS->CreateEvent(EVT_TIMER, 0, 0, NULL, &timer);
307
	if (status != EFI_SUCCESS) {
308
		printf("Can't allocate timer event.\n");
309
		return (-1);
310
	}
311
	printf("  0: AutoSelected Partition (Default): 0\n"); 
312
	for (i = 0; i < ndevs; i++) {
313
		if (dev_list[i].devinfop->preferred == TRUE)
314
			c = '*';
315
		else
316
			c = ' ';
317
		mediapath = efi_devpath_to_media_path(
318
		    dev_list[i].devinfop->devpath);
319
		printf(" %c%c: %s: %s: %s: %c\n", c, idx2char(i+1),
320
		    dev_list[i].modp->name,
321
		    messagingpath_str(dev_list[i].devinfop->devpath),
322
		    mediapath_str(mediapath),
323
		    idx2char(i+1));
324
	}
325
	/* One alpha-num selection only. Is this big enough ?? */
326
	BS->SetTimer(timer, TimerPeriodic, 10000000); 
327
	events[0] = timer;
328
	events[1] = ST->ConIn->WaitForKey;
329
330
	while (1) {
331
		if (time_left > 0) {
332
			printf("Select from 0 to %c. Timeout in %2d seconds,"
333
			       " [Space] to pause : ",
334
			       idx2char(ndevs), time_left);
335
		}
336
		status = BS->WaitForEvent(2, events, &idx);
337
		if (status != EFI_SUCCESS) {
338
			BS->CloseEvent(timer);
339
			return (-1);
340
		}
341
		if (idx == 0) {
342
			time_left--;
343
			if (time_left <=0) {
344
				printf("\nTimeout. "
345
				       "Partition is AutoSelected.\n");
346
				n = 0;
347
				break;
348
			} else {
349
				move_to_tol();
350
			}
351
		}
352
		if (idx == 1) {
353
			c = getchar();
354
			if ((c == '\n') || (c == '\r')) {
355
				putchar('\n');
356
				n = 0;
357
				break;
358
			} else if ((time_left > 0) && (c == ' ')) {
359
				BS->SetTimer(timer, TimerCancel, 0); 
360
				time_left = -1;
361
				printf("\nTimer stopeed.\n Please Key in: ");
362
			}
363
			n = char2idx(c);
364
			if ((n >= 0) && (n <= ndevs)) {
365
				BS->SetTimer(timer, TimerCancel, 0); 
366
				time_left = -1;
367
				printf("\n %c is selected.\n", c);
368
				break;
369
			} else {
370
				/* Invalid charecter. */
371
				move_to_tol();
372
			}
373
		}
374
	};
375
	BS->CloseEvent(timer);
376
	return (n);
377
}
378
379
static EFI_STATUS
380
select_loader(const boot_module_t **modp, dev_info_t **devinfop,
381
    void **bufp, size_t *bufsize)
382
{
383
	int n;
384
	int time_left;
385
	EFI_STATUS status;
386
	dev_info_t *dev;
387
	const boot_module_t *mod;
388
	int ndevs;
389
390
	ndevs = list_devices();
391
	if ((ndevs <= 0) || (ndevs >= NUM_DEV_LIST)) {
392
		return (EFI_NOT_FOUND);
393
	} else if (ndevs == 1) {
394
		/* Only one condidate. */
395
		*modp = mod = dev_list[0].modp;
396
		*devinfop = dev = dev_list[0].devinfop;
397
		return (mod->load(PATH_LOADER_EFI, dev,bufp, bufsize));
398
	}
399
400
	/* Two or more candidate exist. */
401
402
	/* Reset the console input. */
403
	ST->ConIn->Reset(ST->ConIn, TRUE);
404
405
	time_left = SELECT_TIMEOUT;
406
	while (1) {
407
		n = get_sel(ndevs, time_left);
408
		if (n < 0) {
409
			return (EFI_NOT_FOUND);
410
		} else if (n == 0) { /* AutoSelect */
411
			break;
412
		} else {
413
			mod = dev_list[n-1].modp;
414
			dev = dev_list[n-1].devinfop;
415
			status = mod->load(PATH_LOADER_EFI,dev, bufp, bufsize);
416
			if (status == EFI_SUCCESS) {
417
				break;
418
			}
419
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
420
			printf("Please select again: ");
421
			time_left = -1;
422
		}
423
	}
424
	if (n == 0) { /* AutoSelect */
425
		status = load_loader(modp, devinfop, bufp, bufsize, TRUE);
426
		if (status != EFI_SUCCESS) {
427
			status = load_loader(modp, devinfop, bufp, bufsize, FALSE);
428
		}
429
	} else {
430
		*modp = dev_list[n-1].modp;
431
		*devinfop = dev_list[n-1].devinfop;
432
		status = EFI_SUCCESS;
433
	}
434
	return (status);
435
}
436
437
/*
49
 * probe_handle determines if the passed handle represents a logical partition
438
 * probe_handle determines if the passed handle represents a logical partition
50
 * if it does it uses each module in order to probe it and if successful it
439
 * if it does it uses each module in order to probe it and if successful it
51
 * returns EFI_SUCCESS.
440
 * returns EFI_SUCCESS.
Lines 210-222 Link Here
210
		boot_modules[i]->status();
599
		boot_modules[i]->status();
211
	}
600
	}
212
601
213
	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 1);
602
	status = select_loader(&mod, &dev, &loaderbuf, &loadersize);	
214
	if (status != EFI_SUCCESS) {
603
	if (status != EFI_SUCCESS) {
215
		status = load_loader(&mod, &dev, &loaderbuf, &loadersize, 0);
604
		printf("Failed to load '%s'\n", PATH_LOADER_EFI);
216
		if (status != EFI_SUCCESS) {
605
		return;
217
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
218
			return;
219
		}
220
	}
606
	}
221
607
222
	try_boot(mod, dev, loaderbuf, loadersize);
608
	try_boot(mod, dev, loaderbuf, loadersize);

Return to bug 207940