summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsgalabov <sgalabov@FreeBSD.org>2016-03-09 11:45:48 +0000
committersgalabov <sgalabov@FreeBSD.org>2016-03-09 11:45:48 +0000
commit9a94f84b4105b35133c4ba9e48e931c1e0ea0b93 (patch)
tree83244963befc3db595ba429de2f26bf00aa92b46
parent8e3791996d224a0e269c6ada441007e871b0a3b5 (diff)
downloadFreeBSD-src-9a94f84b4105b35133c4ba9e48e931c1e0ea0b93.zip
FreeBSD-src-9a94f84b4105b35133c4ba9e48e931c1e0ea0b93.tar.gz
Improve U-Boot API detection
Until now, ubldr has been trying to locate the U-Boot API using a hint address (U-Boot's current stack pointer), aligning it to 1MiB and going over a 3MiB (or 1MiB in case of MIPS) memory region searching for a valid API signature. This change introduces an alternative way of doing this, namely the following: - both U-Boot's bootelf and go commands actually pass argc and argv to the entry point (e.g., ubldr's start function, but they should also be passed over to main() transparently) - so, instead of trying to go and look for a valid API signature, we look at the parameters passed to main() - if there's an option '-a' with argument, which is a valid hexadecimal unsigned long number (x), we try to verify whether we have a valid API signature at address x. If so - we use it. If not - we fallback to the original way of locating the API signature. The U-Boot change, which causes the API structure address to be exported as an environment variable, was committed to mainline U-Boot as commit 22aa61f707574dd569296f521fcfc46a05f51c48 Reviewed by: andrew, adrian Approved by: adrian (mentor) Sponsored by: Smartcom - Bulgaria AD Differential Revision: https://reviews.freebsd.org/D5492
-rw-r--r--sys/boot/uboot/common/main.c7
-rw-r--r--sys/boot/uboot/lib/glue.c35
-rw-r--r--sys/boot/uboot/lib/glue.h1
3 files changed, 41 insertions, 2 deletions
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index f4fe214..d5c7664 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -387,7 +387,7 @@ probe_disks(int devidx, int load_type, int load_unit, int load_slice,
}
int
-main(void)
+main(int argc, char **argv)
{
struct api_signature *sig = NULL;
int load_type, load_unit, load_slice, load_partition;
@@ -395,12 +395,15 @@ main(void)
const char *ldev;
/*
+ * We first check if a command line argument was passed to us containing
+ * API's signature address. If it wasn't then we try to search for the
+ * API signature via the usual hinted address.
* If we can't find the magic signature and related info, exit with a
* unique error code that U-Boot reports as "## Application terminated,
* rc = 0xnnbadab1". Hopefully 'badab1' looks enough like "bad api" to
* provide a clue. It's better than 0xffffffff anyway.
*/
- if (!api_search_sig(&sig))
+ if (!api_parse_cmdline_sig(argc, argv, &sig) && !api_search_sig(&sig))
return (0x01badab1);
syscall_ptr = sig->syscall;
diff --git a/sys/boot/uboot/lib/glue.c b/sys/boot/uboot/lib/glue.c
index 4c843f0..07db23d 100644
--- a/sys/boot/uboot/lib/glue.c
+++ b/sys/boot/uboot/lib/glue.c
@@ -68,6 +68,41 @@ valid_sig(struct api_signature *sig)
}
/*
+ * Checks to see if API signature's address was given to us as a command line
+ * argument by U-Boot.
+ *
+ * returns 1/0 depending on found/not found result
+ */
+int
+api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig)
+{
+ unsigned long api_address;
+ int c;
+
+ api_address = 0;
+ opterr = 0;
+ optreset = 1;
+ optind = 1;
+
+ while ((c = getopt (argc, argv, "a:")) != -1)
+ switch (c) {
+ case 'a':
+ api_address = strtoul(optarg, NULL, 16);
+ break;
+ default:
+ break;
+ }
+
+ if (api_address != 0) {
+ *sig = (struct api_signature *)api_address;
+ if (valid_sig(*sig))
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
* Searches for the U-Boot API signature
*
* returns 1/0 depending on found/not found result
diff --git a/sys/boot/uboot/lib/glue.h b/sys/boot/uboot/lib/glue.h
index b9c60b6..4c2da66 100644
--- a/sys/boot/uboot/lib/glue.h
+++ b/sys/boot/uboot/lib/glue.h
@@ -58,6 +58,7 @@
int syscall(int, int *, ...);
void *syscall_ptr;
+int api_parse_cmdline_sig(int argc, char **argv, struct api_signature **sig);
int api_search_sig(struct api_signature **sig);
#define UB_MAX_MR 16 /* max mem regions number */
OpenPOWER on IntegriCloud