summaryrefslogtreecommitdiff
path: root/common/cmd_bootscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/cmd_bootscan.c')
-rw-r--r--common/cmd_bootscan.c574
1 files changed, 386 insertions, 188 deletions
diff --git a/common/cmd_bootscan.c b/common/cmd_bootscan.c
index 8a9ad7b75c..fa791ef93b 100644
--- a/common/cmd_bootscan.c
+++ b/common/cmd_bootscan.c
@@ -5,6 +5,7 @@
*/
#include <common.h>
+#include <malloc.h>
#if defined(CONFIG_MENU)
/* Menu related code begins here */
@@ -12,7 +13,9 @@
/* Added to use the various usb and extXfs interfaces */
#include <usb.h>
#include <ext4fs.h>
+#include <fat.h>
#include <menu.h>
+#include <hush.h>
#define BOOTSCAN_MAX_DEVICES 10
#define BOOTSCAN_MAX_PARTITIONS 10
@@ -21,28 +24,19 @@
#define BOOTSCAN_EXIT 1
#define BOOTSCAN_SHOW 2
-#if 0
-#define BOOTSCAN_DFLT_BOOTARGS \
- "setenv bootargs ${console} ubi.mtd=2,2048 " \
- "root=ubi0:root rootfstype=ubifs debug"
-
-#define BOOTSCAN_DFLT_BOOTCMD \
- "setenv bootcmd nand read.e 0x800000 0x100000 0x600000"
-#else
-#define BOOTSCAN_DFLT_BOOTARGS CONFIG_BOOTARGS
+#define BOOTSCAN_DFLT_BOOTARGS CONFIG_BOOTARGS \
+ " console=tty1 console=ttySAC1,115200 hdtv_type=hdmi" \
+ " hdtv_format=720p60hz"
#define BOOTSCAN_DFLT_BOOTCMD CONFIG_BOOTCOMMAND
-#endif
+#define BOOTSCAN_ANDROID_LABEL "Android"
+#define BOOTSCAN_ANDROID_BOOTSCR "boot.scr"
#define BOOTSCAN_PROMPT_BOOTCMD \
"setenv bootcmd echo Dropping you to u-boot"
-#define BOOTSCAN_CHOSEN_BOOTARGS \
- "setenv bootargs ${console} ${mem} rootwait " \
- "root=${" BOOTSCAN_ROOT "} ${hdtv_type} ${hdtv_format}"
-
#define BOOTSCAN_OPTIONS_HEADER \
- "# Root Iface Dev Part FS FileName " \
- "Label UUID\n" \
+ "# Root Iface Dev Part FS FileName " \
+ "Label UUID\n" \
BOOTSCAN_OPTIONS_DIVIDER
#define BOOTSCAN_OPTIONS_DIVIDER \
@@ -52,13 +46,25 @@
#define BOOTSCAN_DFLT_NOBOOTABLES \
"* Last boot options (None, and no bootables found!)"
-#define BOOTSCAN_BOOTARGS "bootscan_bootargs"
#define UBOOT_BOOTARGS "bootargs"
#define BOOTSCAN_BOOTCMD "bootscan_bootcmd"
#define UBOOT_BOOTCMD "bootcmd"
#define BOOTSCAN_CHOICE "bootscan_choice"
#define BOOTSCAN_ROOT "bootscan_root"
+#define BOOTSCAN_BANNER \
+" ___ _ _ _\n" \
+" /___\\__| |_ __ ___ (_) __| |\n" \
+" // // _` | '__/ _ \\| |/ _` |\n" \
+" / \\_// (_| | | | (_) | | (_| |\n" \
+" \\___/ \\__,_|_| \\___/|_|\\__,_|\n" \
+"\n" \
+" _ _ _ _ _ ____\n" \
+" | || | | || | / |___ \\\n" \
+" | || |_| || |_| | __) |\n" \
+" |__ _|__ _| |/ __/\n" \
+" |_| |_| |_|_____|\n"
+
struct bootscan_bootables {
char interface[5];
int device;
@@ -67,132 +73,136 @@ struct bootscan_bootables {
char uuid[37];
char bootimage[64];
char bootinitrd[64];
- char bootscr[64];
- char fstype; /* 'e' => extXfs, '0' => invalid */
+ char bootinit[64];
+ char fstype; /* 'e' => extXfs, 'f' => fat, '0' => invalid */
char rootdev[16];
};
-char *vars[] = { "initrd_high", "fdt_high", "hdtv_type",
- "hdtv_format", "console", "mem", "" };
-char *var_defaults[] = { "0xffffffff", "0xffffffff", "hdmi",
- "720p60hz", "tty1 ttySAC1,115200n8", "" };
-char var_values[sizeof(vars) / sizeof((vars)[0])][64];
+static void display_banner()
+{
+ puts(BOOTSCAN_BANNER);
+}
static void bootscan_menuprint(void *print_buffer)
{
- printf("%s\n", (char *)print_buffer);
+ printf("%s\n", (char *) print_buffer);
}
-/* Return non zero if we got some variables in the env.
- * boot.scr has been loaded at address ptr. It is of length len.
- * What we need to do is try to grab variables like
- * a. initrd_high
- * b. fdt_high
- * c. hdtv_type
- * d. hdtv_format
- * e. mem
- * f. console (multiple definitions)
- * Once we have these variables we shall do a setenv of them
- * Examples:
- * a. setenv initrd_high initrd_high=<whatever>
- * b. etc
- * f. setenv console <console=xyz console=abc ...>
- * Our bootargs shall be setenv bootargs ${console} ${initrd_high}
- * ${fdt_high} ${mem} ${hdtv_type} ${hdtv_format} root...
+/*
+ * We have got a string made up of possibly many lines.
+ * We need to execute these.
+ * We make sure that boot is not executed, by commenting it out
*/
-static int process_scr(void *ptr, int len) {
- char *startptr = (char *) ptr;
- char *endptr = &startptr[len];
- char *sep = " \t=\n\"\r;%{}'$";
- char *beg, *end;
- int i;
- int retval = 0;
- char *s;
- char cmd[128];
-
- end = startptr;
- while (end < endptr) {
- beg = strsep(&end, sep);
- // Now beg has beginning of a possible string. end points
- // to end of that possible string
- if (end == NULL) {
- end = beg + 1;
- continue;
+static void process_bootini(char *buffer, ulong len) {
+char *line = buffer;
+char *beg = buffer;
+char savechar;
+
+ /* Scan thru the buffer and spot the boot command */
+ debug("%s buffer: %p len: %x\n", __func__, buffer, (int) len);
+ while (beg < &buffer[len]) {
+ /* Get a line, note that we need to replace the \0 to \n
+ * back when we are done */
+ line = strsep(&beg, "\n");
+ if (line == NULL) break;
+ debug("line: %s\n", line);
+ /* and remove leading white spaces */
+ line = skip_spaces(line);
+ /* Check if the character after "boot" is some white noice */
+ if ((line[4] < 33) || (line[4] > 126)) {
+ savechar = line[4];
+ line[4] = '\0';
}
- if ((end - beg) < 3) {
- // At least 3 characters long ?
- continue;
- }
- // Got a potential word. Check it out
- debug("Got word: %s\n", beg);
- i = 0;
- while (vars[i][0] != '\0') {
- if (strcmp(vars[i], beg) == 0) {
- // We got a word hit.
- debug("Got a word hit: %s\n", beg);
- // Now extract the following word
- do {
- beg = strsep(&end, sep);
- if (end == NULL)
- end = beg + 1;
- } while (strlen(beg) == 0);
- debug("Extracted word: %s\n", beg);
- // cat it over in its entry if its not the same
- if (strcmp(beg, vars[i])) {
- if (strlen(var_values[i])) {
- // multiple console lines
- strcat(var_values[i], " ");
- strcat(var_values[i], vars[i]);
- strcat(var_values[i], "=");
- }
- strcat(var_values[i], beg);
- }
- }
- i++;
+ /* Check if it is the boot command */
+ if (strcmp(line, "boot") == 0) {
+ /* It sure is! Comment it out! */
+ line[0] = '#';
}
+ if (savechar != '\0')
+ line[4] = savechar;
+
+ /* Revert back the '\n' caused by strsep */
+ beg[-1] = '\n';
}
+ buffer[len] = '\0';
#ifdef DEBUG
- // Lets print out what we got!
- debug("-------------- Words extracted -----------------------\n");
- i = 0;
- while (vars[i][0] != '\0') {
- debug("%s : %s\n", vars[i], var_values[i]);
- i++;
- }
- debug("------------------------------------------------------\n");
+ puts(buffer);
#endif
- // Lets setenv the variables
- i = 0;
- while (vars[i][0] != '\0') {
- if (var_values[i][0] == '\0') {
- // We possibly dont set mem on our own
- // if boot.scr does not refer to it.
- if (strcmp(vars[i], "mem") == 0) {
- i++;
- continue;
- }
- beg = var_defaults[i];
- }
- else
- beg = var_values[i];
- // Generate the env string
- sprintf(cmd, "%s=%s", vars[i], beg);
- debug("Generated env string: %s\n", cmd);
- s = getenv(vars[i]);
- if ( (s == NULL) || strcmp(s, cmd)) {
- setenv(vars[i], cmd);
- retval = 1;
- debug("setenv %s %s\n", vars[i], cmd);
+ /* We just have to run these commands now */
+#ifdef CONFIG_SYS_HUSH_PARSER
+ parse_string_outer(buffer, FLAG_PARSE_SEMICOLON);
+#else
+ Need to define CONFIG_SYS_HUSH_PARSER
+#endif
+
+#ifdef DEBUG
+ run_command("printenv", 0);
+#endif
+}
+
+/*
+ * Most of the code in this function is from common/cmd_source.c
+ * ptr points to the data
+ * len is the length of data
+ * If successful it returns a pointer to the text data.
+ * A NULL return implies it was not successful
+ * If successful it also updates the len variable to the length of text.
+ */
+static char *process_bootscr(void *ptr, ulong *len) {
+ image_header_t *hdr;
+ ulong *data;
+ char *buf;
+
+ switch(genimg_get_format(ptr)) {
+ case IMAGE_FORMAT_LEGACY:
+ hdr = (image_header_t *) ptr;
+
+ if (!image_check_magic (hdr)) {
+ puts ("Bad magic number\n");
+ return NULL;
}
- else {
- debug("Env same value: %s = %s\n", vars[i], s);
+
+ if (!image_check_hcrc (hdr)) {
+ puts ("Bad header crc\n");
+ return NULL;
}
- i++;
+
+ if (!image_check_type (hdr, IH_TYPE_SCRIPT)) {
+ puts ("Bad image type\n");
+ return NULL;
+ }
+
+ /* get length of script */
+ data = (ulong *)image_get_data (hdr);
+
+ if ((*len = uimage_to_cpu (*data)) == 0) {
+ puts ("Empty Script\n");
+ return NULL;
+ }
+
+ /*
+ * scripts are just multi-image files with one component,
+ * seek past the zero-terminated sequence of image lengths
+ * to get to the actual image data
+ */
+ while (*data++);
+
+ /* NULL terminate the text just to be sure */
+ buf = (char *) data;
+ buf[*len] = '\0';
+ break;
+
+ default:
+ puts("Wrong image format.\n");
+ data = NULL;
+ break;
+
}
- return retval;
+ debug("%s data start: %p len: %x\n", __func__, data, (int ) (*len));
+ return (char *) data;
}
/*
@@ -210,12 +220,31 @@ static int evaluate_env()
{
char *s;
int len;
- char command[128];
+ char command[256];
debug("Entering %s\n", __func__);
- run_command("run " BOOTSCAN_BOOTARGS, 0);
+
+ s = getenv(UBOOT_BOOTCMD);
+ if (strncmp(s, "echo", 4) == 0) {
+ /* User wants the u-boot prompt */
+ return BOOTSCAN_EXIT;
+ }
+
+ /* Modify the bootargs as set by boot.scr */
s = getenv(UBOOT_BOOTARGS);
- printf(UBOOT_BOOTARGS " is %s\n", s);
+ debug("%s from boot.XXX is %s\n", UBOOT_BOOTARGS, s);
+ if (s == NULL) {
+ /* Case where bootargs is not set at all */
+ s = BOOTSCAN_DFLT_BOOTARGS;
+ setenv(UBOOT_BOOTARGS, s);
+ }
+ /* Add rootwait as Arch does not set it */
+ sprintf(command, "%s rootwait root=", s);
+ s = getenv(BOOTSCAN_ROOT);
+ strcat(command, s);
+ setenv(UBOOT_BOOTARGS, command);
+ printf(UBOOT_BOOTARGS " is %s\n", command);
+
run_command("run " BOOTSCAN_BOOTCMD, 0);
s = getenv(UBOOT_BOOTCMD);
printf(UBOOT_BOOTCMD " is %s\n", s);
@@ -223,10 +252,6 @@ static int evaluate_env()
/* We failed to boot, present the menu */
return BOOTSCAN_SHOW;
}
- if (strncmp(s, "echo", 4) == 0) {
- /* User wants the u-boot prompt */
- return BOOTSCAN_EXIT;
- }
sprintf(command, "bootm %x", CONFIG_BOOTSCAN_SYS_LOAD_ADDR);
/*
@@ -244,36 +269,90 @@ static int evaluate_env()
return BOOTSCAN_SHOW;
}
+/*
+ * Returns 0 if its not an Android partition else returns 1.
+ */
+static int is_android_partition(struct bootscan_bootables b)
+{
+ debug("%s - b.fstype: %c b.bootinit: %s b.label: %s\n",
+ __func__, b.fstype, b.bootinit, b.label);
+
+ if ( (b.fstype == 'f') &&
+ (strcmp(b.bootinit, BOOTSCAN_ANDROID_BOOTSCR) == 0) &&
+ (strncmp(b.label, BOOTSCAN_ANDROID_LABEL,
+ strlen(BOOTSCAN_ANDROID_LABEL)) == 0) ) {
+ debug("%s - its an Android partition\n", __func__);
+ return 1;
+ }
+ debug("%s - its not an Android partition\n", __func__);
+ return 0;
+}
+
+/* Here we attempt to run Android.
+ * How?
+ * load boot.scr and run it!
+ * If we return from here => we failed to run Android
+ */
+static void run_android(struct bootscan_bootables b)
+{
+char command[128];
+
+ sprintf(command, "fatload %s %d:%d %x %s",
+ b.interface, b.device, b.partition,
+ CONFIG_BOOTSCAN_SYS_LOAD_ADDR, b.bootinit);
+ debug("Issuing command: %s\n", command);
+ if (run_command(command, 0) != 0) {
+ /* Could not load boot.scr */
+ printf("Error reading %s\n", b.bootinit);
+ return;
+ }
+ sprintf(command, "source %x", CONFIG_BOOTSCAN_SYS_LOAD_ADDR);
+ debug("Issuing command: %s\n", command);
+ run_command(command, 0);
+
+ /* If we return here something wrong has happened and we
+ * couldn't boot into Android
+ */
+ return;
+}
+
static int handle_choice(struct bootscan_bootables bootlist[], char *choice)
{
- char *s, *last_choice;
+ char *s, *last_choice, *buffer;
char command[128];
char load_command[16];
- int index, call_saveenv;
- int len;
+ int index, call_saveenv = 0;
+ ulong len;
debug("Entering %s\n", __func__);
- call_saveenv = 0;
- if (choice == NULL) {
- /* Exit menu and let it do its auto boot */
- debug("bootscan: %s choice is null.\n", __func__);
- return BOOTSCAN_EXIT;
- }
- printf("\nYou chose: %s\n", choice);
last_choice = getenv(BOOTSCAN_CHOICE);
if (last_choice == NULL) {
/* User has not yet chosen before */
- setenv(BOOTSCAN_BOOTARGS, BOOTSCAN_DFLT_BOOTARGS);
setenv(BOOTSCAN_BOOTCMD, BOOTSCAN_DFLT_BOOTCMD);
call_saveenv = 1;
debug("bootscan: %s last_choice is NULL\n", __func__);
}
- if (choice[0] == '*') {
- /* User wants same thing that was chosen the last time */
- debug("bootscan: %s choice is *\n", __func__);
- return BOOTSCAN_EXIT;
+
+ if ( (choice == NULL) || choice[0] == '*') {
+ debug("bootscan: %s choice is null or default.\n", __func__);
+ /* This is where we process it like '*' was chosen. Note
+ * that we do have to validate the last choice for two
+ * reasons:
+ * 1. user would have changed boot.XXX and is rebooting
+ * 2. user has removed some devices and hence the choice
+ * numbering is not valid anymore.
+ */
+
+ if (last_choice != NULL)
+ choice = last_choice;
+ else {
+ /* Nothing here -> choose option 0 */
+ choice = "0";
+ }
}
+ printf("\nYou chose:\n%s\n", choice);
+
if (last_choice && strcmp(choice, last_choice) != 0) {
/* Save the choice chosen */
setenv(BOOTSCAN_CHOICE, choice);
@@ -286,18 +365,49 @@ static int handle_choice(struct bootscan_bootables bootlist[], char *choice)
if ( (s == NULL) ||
(strcmp(s, BOOTSCAN_PROMPT_BOOTCMD) != 0) ) {
setenv(BOOTSCAN_BOOTCMD, BOOTSCAN_PROMPT_BOOTCMD);
- saveenv();
+ if (call_saveenv)
+ saveenv();
}
+ run_command(BOOTSCAN_PROMPT_BOOTCMD, 0);
return BOOTSCAN_EXIT;
}
/* Steps to set the env variables to the chosen values */
index = simple_strtoul(choice, NULL, 10);
+ /* Check if this index is valid. As we set it when no choice is
+ * chosen by user and we are using his last choice options.
+ */
+ if ( (bootlist[index].fstype == '0') ||
+ (bootlist[index].fstype == '\0') ) {
+ index = 0;
+ /* If that is also not valid ? */
+ if ((bootlist[index].fstype == '0') ||
+ (bootlist[index].fstype == '\0') ) {
+ /* Give them the u-boot prompt! */
+ setenv(BOOTSCAN_BOOTCMD, BOOTSCAN_PROMPT_BOOTCMD);
+ saveenv();
+ return BOOTSCAN_EXIT;
+ }
+
+ }
+
+ /* Check if its Android. The check if its a fat partition and it
+ * has a boot.scr file and its label is BOOTSCAN_ANDROID_LABEL
+ */
+ if (is_android_partition(bootlist[index]))
+ {
+ run_android(bootlist[index]);
+
+ /* If we return we failed to boot */
+ return BOOTSCAN_SHOW;
+ }
+
/* At least one of UUID or label will be valid */
/* Currently we go by device name, followed by LABEL and
* then by UUID. For LABEL and UUID we need initrd that
* ArchLinuxArm does not have.
+ * Its more convenient if Distros use LABEL to boot.
*/
if (bootlist[index].rootdev[0] != '\0')
sprintf(command, "/dev/%s", bootlist[index].rootdev);
@@ -312,12 +422,6 @@ static int handle_choice(struct bootscan_bootables bootlist[], char *choice)
call_saveenv = 1;
}
- s = getenv(BOOTSCAN_BOOTARGS);
- if ( (s == NULL) || (strcmp(s, BOOTSCAN_CHOSEN_BOOTARGS) != 0) ) {
- setenv(BOOTSCAN_BOOTARGS, BOOTSCAN_CHOSEN_BOOTARGS);
- call_saveenv = 1;
- }
-
switch (bootlist[index].fstype) {
case 'e':
strcpy(load_command, "ext4load");
@@ -326,34 +430,40 @@ static int handle_choice(struct bootscan_bootables bootlist[], char *choice)
return BOOTSCAN_EXIT;
}
- /* Lets process the boot.scr file for gems */
+ /* Lets process the boot init file for gems */
len = 0;
- if (bootlist[index].bootscr[0] != '\0') {
+ if (bootlist[index].bootinit[0] != '\0') {
sprintf(command, "%s %s %d:%d %x %s",
load_command,
bootlist[index].interface,
bootlist[index].device,
bootlist[index].partition,
CONFIG_BOOTSCAN_SYS_LOAD_ADDR,
- bootlist[index].bootscr);
+ bootlist[index].bootinit);
debug("Issuing command: %s\n", command);
if (run_command(command, 0) != 0) {
/* Could not load boot.scr */
printf("Error reading %s ... ignoring\n",
- bootlist[index].bootscr);
+ bootlist[index].bootinit);
}
else {
s = getenv("filesize");
- len = (int) simple_strtoul(s, NULL, 16);
- debug("Read %d bytes from %s\n", len,
- bootlist[index].bootscr);
+ len = simple_strtoul(s, NULL, 16);
+ debug("Read %x bytes from %s\n", (int) len,
+ bootlist[index].bootinit);
}
}
- // We call process_scr() even in the absence of a boot.scr file
- // as it sets some default values.
- call_saveenv += process_scr((void *) CONFIG_BOOTSCAN_SYS_LOAD_ADDR,
- len);
+ // Lets check if its an scr file
+ if (len) {
+ buffer = process_bootscr(
+ (void *) CONFIG_BOOTSCAN_SYS_LOAD_ADDR, &len);
+ if (buffer == NULL) {
+ /* Not a scr file, assume plain text */
+ buffer = (char *) CONFIG_BOOTSCAN_SYS_LOAD_ADDR;
+ }
+ process_bootini(buffer, len);
+ }
/* Lets try to load and check the boot image */
sprintf(command, "%s %s %d:%d %x %s",
@@ -438,6 +548,41 @@ static int handle_choice(struct bootscan_bootables bootlist[], char *choice)
return BOOTSCAN_EXIT;
}
+/*
+ * Our job is to generate a string which holds the name of the bootfile.
+ * If it has a initrd which goes along with it we append it with a []
+ * Inside those brackets, we use the below indicators:
+ * 'I' -> stands for boot image uses initrd.
+ * 's' -> stands for - there is a scr file which shall be used.
+ * 'i' -> stands for - there is a ini file which shall be used.
+ * So the outcome could be: zImage[] - plain zImage
+ * or zImage[I] - zImage with initrd.
+ * or zImage[Ii] - zImage with initrd and ini file.
+ * or zImage[Is] - zImage with initrd and scr file.
+ */
+#define BOOTSCAN_EXT_INI ".ini"
+#define BOOTSCAN_EXT_SCR ".scr"
+static void generate_bid(struct bootscan_bootables b, char *bid)
+{
+ char initrd = ' ';
+ char bootscr = ' ';
+ int len;
+
+ if (b.bootinitrd[0])
+ initrd = 'I';
+ if (b.bootinit[0]) {
+ bootscr = 's'; /* Mark it as an scr for now */
+ /* Lets check if its a .ini file */
+ len = strlen(b.bootinit);
+ if (strcmp(&b.bootinit[len - 4], BOOTSCAN_EXT_INI) == 0) {
+ bootscr = 'i';
+ }
+ }
+ sprintf(bid, "%s[%c%c]", b.bootimage, initrd, bootscr);
+ debug("%s bid generated is: %s\n", __func__, bid);
+ return;
+}
+
static int bootscan_menu(struct bootscan_bootables bootlist[], int bootdelay)
{
int index;
@@ -448,32 +593,29 @@ static int bootscan_menu(struct bootscan_bootables bootlist[], int bootdelay)
char *last_menu_choice;
char choice_menu_entry[64];
char choice_menu[3];
- char bootimagedisp[64];
+ char bid[64];
debug("Entering %s\n", __func__);
+ display_banner();
puts(BOOTSCAN_OPTIONS_DIVIDER "\n");
m = menu_create(BOOTSCAN_OPTIONS_HEADER, 60, 1, bootscan_menuprint,
NULL, NULL);
+
for (index = 0; index < BOOTSCAN_MAX_BOOTABLES; index++) {
if (bootlist[index].fstype == '0')
break;
snprintf(menu_key[index], sizeof(menu_key[index]), "%d", index);
- /* We put a [I] next to boot image to indicate it has initrd */
- if (bootlist[index].bootinitrd[0] == '\0')
- strcpy(bootimagedisp, bootlist[index].bootimage);
- else
- sprintf(bootimagedisp, "%s[I]",
- bootlist[index].bootimage);
+ generate_bid(bootlist[index], bid);
snprintf(menu_entry[index], sizeof(menu_entry[index]),
- "%d %-10s %-6s %d %d %c %-16s %-14s %8.8s-",
+ "%d %-10s %-6s %d %d %c %-18s %-12s %8.8s-",
index,
bootlist[index].rootdev,
bootlist[index].interface,
bootlist[index].device,
bootlist[index].partition,
bootlist[index].fstype,
- bootimagedisp,
+ bid,
bootlist[index].label,
bootlist[index].uuid);
if (menu_item_add(m, menu_key[index], menu_entry[index]) != 1) {
@@ -514,7 +656,8 @@ static int bootscan_menu(struct bootscan_bootables bootlist[], int bootdelay)
}
/* Mark this as the default choice. */
menu_default_set(m, "*");
- if (menu_item_add(m, "+", "+ UBoot prompt") != 1) {
+
+ if (menu_item_add(m, "+", "+ UBoot prompt") != 1) {
menu_destroy(m);
return BOOTSCAN_EXIT;
}
@@ -528,17 +671,44 @@ static int bootscan_menu(struct bootscan_bootables bootlist[], int bootdelay)
* if an initrd is being used, it exists in the same directory - /boot
* This implies that inited names are without path - just file name!
* Same goes for the boot.scr file.
+ * If the volume label is "Android", and its a FAT partition, then
+ * we only do the search for scrs.
*/
static void filesearch(struct bootscan_bootables bootlist[], int *bootindex)
{
char *images[] = { "/boot/uImage", "/boot/zImage", "" };
char *initrds[] = { "uInitrd", "" };
- char *scrs[] = { "boot.scr", "" };
+ char *scrs[] = { "boot.ini", "boot.scr", "" };
char *s;
-
int findex, index;
debug("Entering %s\n", __func__);
+
+ /* Lets do the Android check if its a FAT partition */
+ if ( (bootlist[*bootindex].fstype == 'f') &&
+ (strncmp(bootlist[*bootindex].label, BOOTSCAN_ANDROID_LABEL,
+ strlen(BOOTSCAN_ANDROID_LABEL)) == 0)) {
+ ALLOC_CACHE_ALIGN_BUFFER(char, fatbuf, 512);
+ /* check if boot.scr exists -> read some bytes from file */
+ debug("Android check\n");
+ if (do_fat_read_at(BOOTSCAN_ANDROID_BOOTSCR, 0, fatbuf,
+ ARCH_DMA_MINALIGN, LS_NO)
+ == ARCH_DMA_MINALIGN) {
+ /* We got a hit, lets record it ! */
+ debug(BOOTSCAN_ANDROID_BOOTSCR " exists!\n");
+ strcpy(bootlist[*bootindex].bootinit,
+ BOOTSCAN_ANDROID_BOOTSCR);
+ /* Lets dummy mark the image file as Android */
+ strcpy(bootlist[*bootindex].bootimage,
+ BOOTSCAN_ANDROID_LABEL);
+ (*bootindex)++;
+ }
+ else
+ debug(BOOTSCAN_ANDROID_BOOTSCR " - does not exist!\n");
+ return;
+ }
+
+ /* Lets do the Linux checks now */
findex = 0;
while (images[findex][0] != '\0') {
switch (bootlist[*bootindex].fstype) {
@@ -549,8 +719,16 @@ static void filesearch(struct bootscan_bootables bootlist[], int *bootindex)
}
break;
+ case 'f':
+ findex++;
+ continue;
+
default:
- break;
+ /* Should not come here at all */
+ debug("Unknown FS type: %c\n",
+ bootlist[*bootindex].fstype);
+ findex++;
+ continue;
}
/* Got a hit, record it */
@@ -576,21 +754,21 @@ static void filesearch(struct bootscan_bootables bootlist[], int *bootindex)
/* Lets check if there is a boot.scr in the same dir */
index = 0;
- strcpy(bootlist[*bootindex].bootscr, images[findex]);
- s = strrchr(bootlist[*bootindex].bootscr, '/');
+ strcpy(bootlist[*bootindex].bootinit, images[findex]);
+ s = strrchr(bootlist[*bootindex].bootinit, '/');
while (scrs[index][0] != '\0') {
strcpy(s + 1, scrs[index]);
- if (ext4fs_open(bootlist[*bootindex].bootscr)
+ if (ext4fs_open(bootlist[*bootindex].bootinit)
== -1) {
index++;
continue;
}
- debug("scr: %s\n", bootlist[*bootindex].bootscr);
+ debug("scr: %s\n", bootlist[*bootindex].bootinit);
break;
}
/* If we didnt get a boot.scr let it be reflected */
if (scrs[index][0] == '\0')
- bootlist[*bootindex].bootscr[0] = '\0';
+ bootlist[*bootindex].bootinit[0] = '\0';
findex++;
(*bootindex)++;
@@ -608,6 +786,10 @@ static void populate_partitions(struct bootscan_bootables *bootlist,
{
int part;
disk_partition_t disk_part;
+ /* Below for fat fs */
+ boot_sector bs;
+ volume_info volinfo;
+ int fatsize;
debug("Entering %s\n", __func__);
part = bootlist[*bootindex].partition;
@@ -631,6 +813,20 @@ static void populate_partitions(struct bootscan_bootables *bootlist,
ext4fs_close();
return;
}
+ else if (fat_set_blk_dev(dev_desc, &disk_part) == 0) {
+ /* It looks like this is fat */
+ if (read_bootsectandvi(&bs, &volinfo, &fatsize))
+ return;
+ bootlist[*bootindex].fstype = 'f';
+ /* Update label name and uuid */
+ strncpy(bootlist[*bootindex].label, volinfo.volume_label, 11);
+ bootlist[*bootindex].label[11] = '\0';
+ strcpy(bootlist[*bootindex].uuid, disk_part.uuid);
+ debug("FAT label: %s uuid: %s\n", bootlist[*bootindex].label,
+ bootlist[*bootindex].uuid);
+ filesearch(bootlist, bootindex);
+ return;
+ }
}
static void populate_devices(struct bootscan_bootables bootlist[],
@@ -658,7 +854,7 @@ static void populate_devices(struct bootscan_bootables bootlist[],
static void populate_bootlist(struct bootscan_bootables bootlist[])
{
/* Order is important - mimic how linux would number the devices */
- char *interfaces[] = { "ide", "usb", "mmc", "" };
+ char *interfaces[] = { "mmc", "ide", "usb", "" };
char mmcdrive, usbdrive;
int bootindex;
int i;
@@ -722,10 +918,11 @@ static void populate_bootlist(struct bootscan_bootables bootlist[])
break;
/* Lets update rootdev
* Logic is as follows -
+ * mmc -> mmc and device # change => mmcdrive++
+ * mmc -> XXX => usbdrive = 'a'
* ide -> usb => usbdrive++
* ide -> ide and device # change => usbdrive++
* usb -> usb and device # change => usbdrive++
- * mmc -> mmc and device # change => mmcdrive++
* XXX -> mmc => mmcdrive = '0'
*/
if (strcmp(bootlist[i].interface, bootlist[i-1].interface)
@@ -738,10 +935,10 @@ static void populate_bootlist(struct bootscan_bootables bootlist[])
}
else {
/* The interface has changed */
- if (strcmp(bootlist[i].interface, "mmc") == 0)
- mmcdrive = '0';
+ if (strcmp(bootlist[i-1].interface, "mmc") == 0)
+ usbdrive = 'a';
else
- usbdrive++;
+ mmcdrive = '0';
}
if (strcmp(bootlist[i].interface, "mmc") == 0) {
/* Its mmc, its mmcblk + dev + 'p' + part */
@@ -752,7 +949,7 @@ static void populate_bootlist(struct bootscan_bootables bootlist[])
sprintf(bootlist[i].rootdev, "sd%c%d", usbdrive,
bootlist[i].partition);
}
- }
+ }
}
@@ -762,11 +959,12 @@ int menu_show(int bootdelay)
int retval;
debug("Entering %s\n", __func__);
+ memset(bootlist, 0, sizeof(bootlist));
populate_bootlist(bootlist);
do {
retval = bootscan_menu(bootlist, bootdelay);
if (retval == BOOTSCAN_EXIT)
- evaluate_env();
+ evaluate_env(bootlist);
} while (retval == BOOTSCAN_SHOW);
return 0;