diff options
author | sgalabov <sgalabov@FreeBSD.org> | 2016-03-09 11:45:48 +0000 |
---|---|---|
committer | sgalabov <sgalabov@FreeBSD.org> | 2016-03-09 11:45:48 +0000 |
commit | 9a94f84b4105b35133c4ba9e48e931c1e0ea0b93 (patch) | |
tree | 83244963befc3db595ba429de2f26bf00aa92b46 | |
parent | 8e3791996d224a0e269c6ada441007e871b0a3b5 (diff) | |
download | FreeBSD-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.c | 7 | ||||
-rw-r--r-- | sys/boot/uboot/lib/glue.c | 35 | ||||
-rw-r--r-- | sys/boot/uboot/lib/glue.h | 1 |
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 */ |