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
This commit is contained in:
Stanislav Galabov 2016-03-09 11:45:48 +00:00
parent 7370229e8d
commit 08190ef7de
3 changed files with 41 additions and 2 deletions

View File

@ -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;

View File

@ -67,6 +67,41 @@ valid_sig(struct api_signature *sig)
return (1);
}
/*
* 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
*

View File

@ -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 */