FreeBSD Bugzilla – Attachment 169420 Details for
Bug 207940
stand/efi/boot1: Add boot partition selection
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
small change
boot1.c.diff (text/plain), 9.69 KB, created by
Masachika ISHIZUKA
on 2016-04-18 05:22:53 UTC
(
hide
)
Description:
small change
Filename:
MIME Type:
Creator:
Masachika ISHIZUKA
Created:
2016-04-18 05:22:53 UTC
Size:
9.69 KB
patch
obsolete
>--- boot1.c.orig 2016-03-05 19:13:54.313402000 +0900 >+++ boot1.c 2016-04-18 13:54:57.265973000 +0900 >@@ -28,7 +28,7 @@ > #include <stand.h> > > #include <efi.h> >-#include <eficonsctl.h> >+#include <efilib.h> > > #include "boot_module.h" > #include "paths.h" >@@ -47,17 +47,51 @@ > /* The initial number of handles used to query EFI for partitions. */ > #define NUM_HANDLES_INIT 24 > >+void efi_cons_putchar(int); >+int efi_cons_getchar(void); >+int efi_cons_poll(void); >+int getchar(void); > void putchar(int c); >+char *humanize_number_kmgt(UINT64); > EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab); > > EFI_SYSTEM_TABLE *systab; > EFI_BOOT_SERVICES *bs; > static EFI_HANDLE *image; >+static SIMPLE_TEXT_OUTPUT_INTERFACE *conout; >+static SIMPLE_INPUT_INTERFACE *conin; > > static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; > static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; > static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; >-static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; >+ >+#define DEFAULT_FGCOLOR EFI_LIGHTGRAY >+#define DEFAULT_BGCOLOR EFI_BLACK >+ >+char *humanize_number_kmgt(UINT64 size) { >+ static char buf2[6]; >+ UINT64 size0; >+ >+ if (size < 1024) >+ sprintf(buf2, "%luB", size); >+ else if (size0 = (size*10+512)/1024, size0 < 100) >+ sprintf(buf2, "%lu.%luK", size0 / 10, size0 % 10); >+ else if (size0 = (size+512)/1024, size0 < 1024) >+ sprintf(buf2, "%luK", size0); >+ else if (size0 = (size*10/1024+512)/1024, size0 < 100) >+ sprintf(buf2, "%lu.%luM", size0 / 10, size0 % 10); >+ else if (size0 = (size/1024+512)/1024, size0 < 1024) >+ sprintf(buf2, "%luM", size0); >+ else if (size0 = (size*10/1024/1024+512)/1024, size0 < 100) >+ sprintf(buf2, "%lu.%luG", size0 / 10, size0 % 10); >+ else if (size0 = (size/1024/1024+512)/1024, size0 < 1024) >+ sprintf(buf2, "%luG", size0); >+ else if (size0 = (size*10/1024/1024/1024+512)/1024, size0 < 100) >+ sprintf(buf2, "%lu.%luT", size0 / 10, size0 % 10); >+ else >+ sprintf(buf2, "%luT", (size/1024/1024/1024+512)/1024); >+ return(buf2); >+} > > /* > * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures >@@ -151,7 +185,6 @@ > static int > devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath) > { >- > switch (devpath->Type) { > case MESSAGING_DEVICE_PATH: > switch (devpath->SubType) { >@@ -251,8 +284,9 @@ > HARDDRIVE_DEVICE_PATH *hd; > > hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath; >- return snprintf(buf, size, "hd(%x)", >- hd->PartitionNumber); >+ return snprintf(buf, size, "hd(p%d) (%s)", >+ hd->PartitionNumber, >+ humanize_number_kmgt(hd->PartitionSize * 512)); > } > default: > return snprintf(buf, size, "media(0x%02x)", >@@ -350,6 +384,99 @@ > return (EFI_NOT_FOUND); > } > >+/* quick dirty work. */ >+#define NUM_DEV_LIST 35 >+ >+static struct dev_list_t { >+ const boot_module_t *modp; >+ dev_info_t *devinfop; >+} dev_list[NUM_DEV_LIST]; >+ >+static int >+list_devices(void) >+{ >+ UINTN i, j; >+ dev_info_t *dev; >+ const boot_module_t *mod; >+ >+ j = 0; >+ for (i = 0; i < NUM_BOOT_MODULES; i++) { >+ if (boot_modules[i] == NULL) >+ continue; >+ mod = boot_modules[i]; >+ for (dev = mod->devices(); dev != NULL; dev = dev->next) { >+ dev_list[j].devinfop = dev; >+ dev_list[j].modp = mod; >+ j++; >+ if (j >= NUM_DEV_LIST) >+ break; >+ } >+ } >+ >+ return (j); >+} >+ >+#define SELECT_TIMEOUT 10 >+ >+static int >+select_dev(int ndevs) >+{ >+ int i; >+ int c; >+ static int timeout = TRUE; >+ >+ printf(" 0: AutoSelected Partition (Default): 0\n"); >+ for (i = 0; i < ndevs; i++) { >+ if (dev_list[i].devinfop->preferred == TRUE) >+ c = '*'; >+ else >+ c = ' '; >+ printf(" %c%c: %s: %s: %c\n", c, i<9 ? '1'+i : 'a'+i-9, >+ dev_list[i].modp->name, >+ devpath_str(dev_list[i].devinfop->devpath), >+ i<9 ? '1'+i : 'a'+i-9); >+ } >+ /* One digit selection only. Is this big enough ?? */ >+ while (1) { >+ if (timeout) >+ printf("Select from 0 to %c: Timeout in %2d seconds" >+ "\b\b\b\b\b\b\b\b\b\b", >+ ndevs<10 ? '0'+ndevs : 'a'+ndevs-10, >+ SELECT_TIMEOUT); >+ else >+ printf("Select from 0 to %c: Never timeout", >+ ndevs<10 ? '0'+ndevs : 'a'+ndevs-10); >+ for (i = SELECT_TIMEOUT * 20; i > 0; i--) { >+ if (timeout) { >+ if (!(i % 20)) >+ printf("%2d\b\b", i / 20); >+ bs->Stall(50000); >+ if (!efi_cons_poll()) /* No Key */ >+ continue; >+ } >+ while (1) { >+ if (timeout) { >+ printf("\b\b\b\b\b\b\b\b\b\b\b" >+ "Never timeout "); >+ timeout = FALSE; >+ } >+ c = getchar(); >+ c = (c == 0x0d) ? 0 : >+ (c >= '0' && c <= '9') ? c - '0' : >+ (c >= 'A' && c <= 'Z') ? c - 'A' + 10 : >+ (c >= 'a' && c <= 'z') ? c - 'a' + 10 : >+ ndevs + 1; >+ if ((c >= 0) && (c <= ndevs)) { >+ putchar('\n'); >+ return (c); >+ } >+ } >+ } >+ printf(" 0\nTimeout. Partition is AutoSelected.\n"); >+ return (0); >+ } >+} >+ > /* > * try_boot only returns if it fails to load the loader. If it succeeds > * it simply boots, otherwise it returns the status of last EFI call. >@@ -358,22 +485,54 @@ > try_boot() > { > size_t bufsize, loadersize, cmdsize; >- void *buf, *loaderbuf; >+ void *buf = NULL, *loaderbuf = NULL; > char *cmd; > dev_info_t *dev; > const boot_module_t *mod; > EFI_HANDLE loaderhandle; > EFI_LOADED_IMAGE *loaded_image; > EFI_STATUS status; >+ int i, ndevs; > >- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); >- if (status != EFI_SUCCESS) { >- status = load_loader(&mod, &dev, &loaderbuf, &loadersize, >- FALSE); >+ ndevs = list_devices(); >+ if (ndevs == 0) { >+ printf("Failed to load '%s'\n", PATH_LOADER_EFI); >+ return (EFI_NOT_FOUND); >+ } else if (ndevs == 1) { >+ mod = dev_list[0].modp; >+ dev = dev_list[0].devinfop; >+ status = mod->load(PATH_LOADER_EFI, dev, >+ &loaderbuf, &loadersize); > if (status != EFI_SUCCESS) { > printf("Failed to load '%s'\n", PATH_LOADER_EFI); > return (status); > } >+ } else { >+ while (1) { >+ i = select_dev(ndevs); >+ printf(" %c is selected.\n", i<10 ? '0'+i : 'a'+i-10); >+ if (i == 0) { /* AutoSelect */ >+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE); >+ if (status != EFI_SUCCESS) { >+ status = load_loader(&mod, &dev, &loaderbuf, &loadersize, >+ FALSE); >+ if (status != EFI_SUCCESS) { >+ printf("Failed to load '%s'\n", PATH_LOADER_EFI); >+ return (status); >+ } >+ } >+ break; >+ } else { >+ mod = dev_list[i-1].modp; >+ dev = dev_list[i-1].devinfop; >+ status = mod->load(PATH_LOADER_EFI, dev, >+ &loaderbuf, &loadersize); >+ if (status == EFI_SUCCESS) >+ break; >+ printf("Failed to load '%s'\n", PATH_LOADER_EFI); >+ } >+ printf("Please select again.\n"); >+ } > } > > /* >@@ -423,6 +582,9 @@ > loaded_image->LoadOptionsSize = cmdsize; > loaded_image->LoadOptions = cmd; > >+ printf("Boot from: %s in 1 second\n", devpath_str(dev->devpath)); >+ bs->Stall(1000000); >+ > DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI); > DSTALL(1000000); > DPRINTF("."); >@@ -556,36 +718,24 @@ > DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status)); > break; > } >- DSTALL(500000); >+ DSTALL(1000000); > } > >-EFI_STATUS >-efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) >+static EFI_STATUS >+init_console() > { >- EFI_HANDLE *handles; >- EFI_LOADED_IMAGE *img; >- EFI_DEVICE_PATH *imgpath; > EFI_STATUS status; >- EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; >- SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL; >- UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles; >- >- /* Basic initialization*/ >- systab = Xsystab; >- image = Ximage; >- bs = Xsystab->BootServices; >+ UINTN i, max_dim, best_mode, cols, rows; > > /* Set up the console, so printf works. */ >- status = bs->LocateProtocol(&ConsoleControlGUID, NULL, >- (VOID **)&ConsoleControl); >- if (status == EFI_SUCCESS) >- (void)ConsoleControl->SetMode(ConsoleControl, >- EfiConsoleControlScreenText); > /* > * Reset the console and find the best text mode. > */ >+ conin = systab->ConIn; > conout = systab->ConOut; >+ conin->Reset(conin, TRUE); > conout->Reset(conout, TRUE); >+ > max_dim = best_mode = 0; > for (i = 0; ; i++) { > status = conout->QueryMode(conout, i, &cols, &rows); >@@ -598,9 +748,31 @@ > } > if (max_dim > 0) > conout->SetMode(conout, best_mode); >+ >+ conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR, >+ DEFAULT_BGCOLOR)); > conout->EnableCursor(conout, TRUE); > conout->ClearScreen(conout); > >+ return (status); >+} >+ >+EFI_STATUS >+efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab) >+{ >+ EFI_HANDLE *handles; >+ EFI_LOADED_IMAGE *img; >+ EFI_DEVICE_PATH *imgpath; >+ EFI_STATUS status; >+ UINTN i, hsize, nhandles; >+ >+ /* Basic initialization*/ >+ systab = Xsystab; >+ image = Ximage; >+ bs = Xsystab->BootServices; >+ >+ init_console(); >+ > printf("\n>> FreeBSD EFI boot block\n"); > printf(" Loader path: %s\n\n", PATH_LOADER_EFI); > printf(" Initializing modules:"); >@@ -715,14 +887,57 @@ > void > putchar(int c) > { >+ efi_cons_putchar(c); >+} >+ >+void >+efi_cons_putchar(int c) >+{ > CHAR16 buf[2]; > > if (c == '\n') { > buf[0] = '\r'; > buf[1] = 0; >- systab->ConOut->OutputString(systab->ConOut, buf); >+ conout->OutputString(conout, buf); > } > buf[0] = c; > buf[1] = 0; >- systab->ConOut->OutputString(systab->ConOut, buf); >+ conout->OutputString(conout, buf); >+} >+ >+int >+getchar(void) >+{ >+ return efi_cons_getchar(); >+} >+ >+ >+int >+efi_cons_getchar() >+{ >+ EFI_INPUT_KEY key; >+ EFI_STATUS status; >+ UINTN junk; >+ >+ /* Try to read a key stroke. We wait for one if none is pending. */ >+ status = conin->ReadKeyStroke(conin, &key); >+ if (status == EFI_NOT_READY) { >+ bs->WaitForEvent(1, &conin->WaitForKey, &junk); >+ status = conin->ReadKeyStroke(conin, &key); >+ } >+ switch (key.ScanCode) { >+ case 0x17: /* ESC */ >+ return (0x1b); /* esc */ >+ } >+ >+ /* this can return */ >+ return (key.UnicodeChar); > } >+ >+int >+efi_cons_poll() >+{ >+ /* This can clear the signaled state. */ >+ return (bs->CheckEvent(conin->WaitForKey) == EFI_SUCCESS); >+} >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 207940
:
168070
|
168264
|
168291
|
169420
|
170131
|
170241
|
194818
|
201259
|
201260
|
205099
|
205561
|
205563
|
212457
|
212647
|
246766