diff mbox series

[U-Boot,v2,3/8] cmd: bootimg: Add bootimg command

Message ID 20191023143427.10865-4-semen.protsenko@linaro.org
State Changes Requested
Delegated to: Tom Rini
Headers show
Series am57xx: Implement Android 10 boot flow | expand

Commit Message

Sam Protsenko Oct. 23, 2019, 2:34 p.m. UTC
This command can be used to extract fields and image payloads from
Android Boot Image. It can be used for example to implement boot flow
where dtb is taken from boot.img (as v2 incorporated dtb inside of
boot.img). Using this command, one can obtain needed dtb file from
boot.img in scripting manner, and then apply needed dtbo's (from "dtbo"
partition) on top of that, providing then the resulting image to bootm
command in order to boot the Android.

Also right now this command has the sub-command to get an address and
size of recovery dtbo from recovery image. It can be further parsed using
'dtimg' command and merged into dtb file (for non-A/B devices only, see
[1,2] for details).

[1] https://source.android.com/devices/bootloader/boot-image-header
[2] https://source.android.com/devices/architecture/dto/partitions

Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
---
Changes in v2:
  - add "set_addr" sub-command
  - provide mem mappings for sandbox
  - rebase on top of master

 cmd/Kconfig   |   8 ++
 cmd/Makefile  |   1 +
 cmd/bootimg.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+)
 create mode 100644 cmd/bootimg.c

Comments

Simon Glass Oct. 30, 2019, 1:48 a.m. UTC | #1
Hi Sam,

On Wed, 23 Oct 2019 at 08:34, Sam Protsenko <semen.protsenko@linaro.org> wrote:
>
> This command can be used to extract fields and image payloads from
> Android Boot Image. It can be used for example to implement boot flow
> where dtb is taken from boot.img (as v2 incorporated dtb inside of
> boot.img). Using this command, one can obtain needed dtb file from
> boot.img in scripting manner, and then apply needed dtbo's (from "dtbo"
> partition) on top of that, providing then the resulting image to bootm
> command in order to boot the Android.
>
> Also right now this command has the sub-command to get an address and
> size of recovery dtbo from recovery image. It can be further parsed using
> 'dtimg' command and merged into dtb file (for non-A/B devices only, see
> [1,2] for details).
>
> [1] https://source.android.com/devices/bootloader/boot-image-header
> [2] https://source.android.com/devices/architecture/dto/partitions
>
> Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
> ---
> Changes in v2:
>   - add "set_addr" sub-command
>   - provide mem mappings for sandbox
>   - rebase on top of master
>
>  cmd/Kconfig   |   8 ++
>  cmd/Makefile  |   1 +
>  cmd/bootimg.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 219 insertions(+)
>  create mode 100644 cmd/bootimg.c

Sorry I still think this name 'bootimg' is confusing. How would anyone
know that it is specific to Android?

How about abootimg?

Regards,
Simon
Eugeniu Rosca Nov. 27, 2019, 7:16 p.m. UTC | #2
Hi Sam,

On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> +static int do_bootimg_get_dtb_file(cmd_tbl_t *cmdtp, int flag, int argc,
> +				   char * const argv[])
> +{
> +	char *endp;
> +	char buf[65];
> +	u32 index;
> +	ulong addr;
> +	u32 size;
> +
> +	if (argc < 3 || argc > 4)
> +		return CMD_RET_USAGE;
> +
> +	index = simple_strtoul(argv[1], &endp, 0);
> +	if (*endp != '\0') {
> +		printf("Error: Wrong index\n");
> +		return CMD_RET_FAILURE;
> +	}
> +
> +	if (!android_image_get_dtb_by_index(bootimg_addr(), index, &addr,
> +					    &size))

As discussed in https://patchwork.ozlabs.org/patch/958594/#2302310, we
try to enhance the "dtimg" U-Boot command to be able to identify DT
blobs by "id" or "rev" [*] field value.

It's quite challenging in this context to avoid conflicting with your
recently proposed "bootimg" command, since the latter makes use of the
android_image_get_dtb_by_index API, which is subject of modification
and/or renaming.

I am willing to cooperate to entirely avoid or reconcile the conflict
in the best possible way, but for that I need your feedback.

[*] https://source.android.google.cn/devices/architecture/dto/partitions
Sam Protsenko Dec. 2, 2019, 7:07 p.m. UTC | #3
Hi Eugeniu,

On Wed, Nov 27, 2019 at 9:17 PM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>
> Hi Sam,
>
> On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > +static int do_bootimg_get_dtb_file(cmd_tbl_t *cmdtp, int flag, int argc,
> > +                                char * const argv[])
> > +{
> > +     char *endp;
> > +     char buf[65];
> > +     u32 index;
> > +     ulong addr;
> > +     u32 size;
> > +
> > +     if (argc < 3 || argc > 4)
> > +             return CMD_RET_USAGE;
> > +
> > +     index = simple_strtoul(argv[1], &endp, 0);
> > +     if (*endp != '\0') {
> > +             printf("Error: Wrong index\n");
> > +             return CMD_RET_FAILURE;
> > +     }
> > +
> > +     if (!android_image_get_dtb_by_index(bootimg_addr(), index, &addr,
> > +                                         &size))
>
> As discussed in https://patchwork.ozlabs.org/patch/958594/#2302310, we
> try to enhance the "dtimg" U-Boot command to be able to identify DT
> blobs by "id" or "rev" [*] field value.
>
> It's quite challenging in this context to avoid conflicting with your
> recently proposed "bootimg" command, since the latter makes use of the
> android_image_get_dtb_by_index API, which is subject of modification
> and/or renaming.
>
> I am willing to cooperate to entirely avoid or reconcile the conflict
> in the best possible way, but for that I need your feedback.
>

I'd like this patch series to be applied ASAP (probably before DTBO
patches you mention are merged). It's been too long as it is. Once
merged and we are unblocked w.r.t. Android boot stuff, we can then
look into DTBO changes you mention, and if any C API are changed, we
can change those usage overall the U-Boot tree. Hope you agree. I will
help you guys to figure out all DTBO related changes further, but
please let's get this patch series over with...

Thanks!

> [*] https://source.android.google.cn/devices/architecture/dto/partitions
>
> --
> Best Regards,
> Eugeniu
Eugeniu Rosca Dec. 3, 2019, 7:29 p.m. UTC | #4
Hi Sam,
Cc: Aleksandr, Roman

As expressed in the attached e-mail, to minimize the headaches extending
the argument list of "bootimg" in future, can we please agree on below?

On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> +U_BOOT_CMD(
> +	bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> +	"manipulate Android Boot Image",
> +	"set_addr <addr>\n"
> +	"    - set the address in RAM where boot image is located\n"
> +	"      ($loadaddr is used by default)\n"
> +	"bootimg ver <varname>\n"

Can we make <varname> optional, with the background provided in [1]?

> +	"    - get header version\n"
> +	"bootimg get_dtbo <addr_var> [size_var]\n"

How about converting <addr_var> to an optional argument too?

> +	"    - get address and size (hex) of recovery DTBO area in the image\n"
> +	"      <addr_var>: variable name to contain DTBO area address\n"
> +	"      [size_var]: variable name to contain DTBO area size\n"
> +	"bootimg dtb_dump\n"
> +	"    - print info for all files in DTB area\n"
> +	"bootimg dtb_load_addr <varname>\n"

Same as above w.r.t. <varname>.

> +	"    - get load address (hex) of DTB\n"
> +	"bootimg get_dtb_file <index> <addr_var> [size_var]\n"

How about converting <addr_var> to an optional argument too?
How do you foresee getting a blob entry based on id=<i> and/or
rev=<r>? Which of below is your favorite option?

 - get_dtb_file <index> [--id=<i>] [--rev=<r>] [addr_var] [size_var]
   where: - in case <i> and/or <r> are provided, <index> tells the
            command to pick the N's entry in the selection filtered by
            <i> and <r>
          - in case neither <i> nor <r> is provided, <index>
            behaves like in the current patch (selects a blob entry
            found at absolute index value ${index} in the image)

 - get_dtb_file [<index>|[--id=<i>|--rev=<r>]] [addr_var] [size_var]
   To make it clear, some example commands would be:
   - get_dtb_file <index>
     => current behavior
   - get_dtb_file --id=<i>
     => get _first_ blob entry matching id value <i>
   - get_dtb_file --rev=<r>
     => get _first_ blob entry matching rev value <r>
   - get_dtb_file --id=<i> --rev=<r>
     => get _first_ blob entry matching id <i> _and_ rev=<r>
   - get_dtb_file <index> --id=<i>
   - get_dtb_file <index> --rev=<r>
     => Wrong usage

 - get_dtb_file  anything else?

I think it is crucial to agree on the above, since the very first
revision of "bootimg"/"abootimg" may impose strict limitations on how
the command can be extended in future.

[just noticed your reply shedding more light on a subset of these
questions, but still sending this out; please skip if already answered]

> +	"    - get address and size (hex) of DTB file in the image\n"
> +	"      <index>: index of desired DTB file in DTB area\n"
> +	"      <addr_var>: variable name to contain DTB file address\n"
> +	"      [size_var]: variable name to contain DTB file size\n"
> +);

[1] https://patchwork.ozlabs.org/patch/1202579/
    ("cmd: dtimg: Make <varname> an optional argument")
Eugeniu Rosca Dec. 4, 2019, 5:22 p.m. UTC | #5
Hi Sam,

On Mon, Dec 02, 2019 at 09:07:15PM +0200, Sam Protsenko wrote:
> I'd like this patch series to be applied ASAP (probably before DTBO
> patches you mention are merged). It's been too long as it is. Once
> merged and we are unblocked w.r.t. Android boot stuff, we can then
> look into DTBO changes you mention, and if any C API are changed, we
> can change those usage overall the U-Boot tree. Hope you agree. I will
> help you guys to figure out all DTBO related changes further, but
> please let's get this patch series over with...
> 
> Thanks!

[to avoid this comment of yours unanswered]

I am ready to provide the Reviewed-by for your Android 10 series,
as soon as the review points summarized in [*] are taken care of.

[*] https://patchwork.ozlabs.org/patch/1182207/#2317118
Eugeniu Rosca Dec. 4, 2019, 5:33 p.m. UTC | #6
Hello Sam,
Please, see one more suggestion below.

On Tue, Dec 03, 2019 at 08:29:10PM +0100, Eugeniu Rosca wrote:
> Hi Sam,
> Cc: Aleksandr, Roman
> 
> As expressed in the attached e-mail, to minimize the headaches extending
> the argument list of "bootimg" in future, can we please agree on below?
> 
> On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > +U_BOOT_CMD(
> > +	bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> > +	"manipulate Android Boot Image",
> > +	"set_addr <addr>\n"
> > +	"    - set the address in RAM where boot image is located\n"
> > +	"      ($loadaddr is used by default)\n"
> > +	"bootimg ver <varname>\n"
> 
> Can we make <varname> optional, with the background provided in [1]?
> 
> > +	"    - get header version\n"
> > +	"bootimg get_dtbo <addr_var> [size_var]\n"
> 
> How about converting <addr_var> to an optional argument too?
> 
> > +	"    - get address and size (hex) of recovery DTBO area in the image\n"
> > +	"      <addr_var>: variable name to contain DTBO area address\n"
> > +	"      [size_var]: variable name to contain DTBO area size\n"
> > +	"bootimg dtb_dump\n"
> > +	"    - print info for all files in DTB area\n"
> > +	"bootimg dtb_load_addr <varname>\n"
> 
> Same as above w.r.t. <varname>.
> 
> > +	"    - get load address (hex) of DTB\n"
> > +	"bootimg get_dtb_file <index> <addr_var> [size_var]\n"

How about "get_dte" or "get_dtbe" instead of "get_dtb_file" ?
It's shorter and should be easier to remember (dt{b}e = DT{B} Entry).
Eugeniu Rosca Dec. 4, 2019, 6:25 p.m. UTC | #7
Hi again,

[I would be willing to take this discussion offline, if you consider it
too noisy for ML]

On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> +U_BOOT_CMD(
> +	bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> +	"manipulate Android Boot Image",
> +	"set_addr <addr>\n"
> +	"    - set the address in RAM where boot image is located\n"
> +	"      ($loadaddr is used by default)\n"
> +	"bootimg ver <varname>\n"
> +	"    - get header version\n"
> +	"bootimg get_dtbo <addr_var> [size_var]\n"
> +	"    - get address and size (hex) of recovery DTBO area in the image\n"
> +	"      <addr_var>: variable name to contain DTBO area address\n"
> +	"      [size_var]: variable name to contain DTBO area size\n"
> +	"bootimg dtb_dump\n"
> +	"    - print info for all files in DTB area\n"

I now see that "DTBO area" is used intermixed with "DTB area".
I think it makes sense to use one of the two consistently and drop the
other. Otherwise, users might think there are two distinct areas in
the same Android image.

> +	"bootimg dtb_load_addr <varname>\n"
> +	"    - get load address (hex) of DTB\n"

This is actually not something retrieved from the DTB/DTBO area, but
from the "dtb_addr" field of the Android Image itself, as defined in
https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h

I think this little bit of information is essential, but not sure how to
make it more transparent to the user, since purely based on the
available help message, I tend to infer that there is connection between
"DTB" in "get load address (hex) of DTB" and the "DTBO area", while
there is no connection whatsoever.

> +	"bootimg get_dtb_file <index> <addr_var> [size_var]\n"
> +	"    - get address and size (hex) of DTB file in the image\n"
> +	"      <index>: index of desired DTB file in DTB area\n"
> +	"      <addr_var>: variable name to contain DTB file address\n"
> +	"      [size_var]: variable name to contain DTB file size\n"

Would it make more sense to use "DTB entry" instead of "DTB file"
since this is the wording used in the Google spec/header?

Another general comment regarding the current sub-commands:
 - set_addr
 - ver
 - get_dtbo
 - dtb_dump
 - dtb_load_addr
 - get_dtb_file

I observe the following (inconsistent) pattern:
 - <do>_<what>
 - <what>
 - <do>_<what>
 - <what>_<do>
 - <what>_<do>_<what>
 - <do>_<what>

Looking at the "fdt" command, I find its sub-commands
somehow better partitioned and easier to digest/remember:

fdt addr [-c]  <addr> [<length>]
fdt apply <addr>
fdt move   <fdt> <newaddr> <length>
fdt resize [<extrasize>]
fdt print  <path> [<prop>]
fdt list   <path> [<prop>]
fdt get value <var> <path> <prop>
fdt get name <var> <path> <index>
fdt get addr <var> <path> <prop>
fdt get size <var> <path> [<prop>]
fdt set    <path> <prop> [<val>]
fdt mknode <path> <node>
fdt rm     <path> [<prop>]
fdt header [get <var> <member>]

Its syntax seems to be:
 <command> <do> <what> [options]

Would it make sense to borrow this naming style/principle?
It could translate to the following for abootimg:

abootimg (current sub-command name enclosed in brackets):
 - addr (set_addr)
 - ver
 - dump dtbo (dtb_dump)
 - get dtbo (get_dtbo)
 - get dtbe (get_dtb_file)
 - get dtla (dtb_load_addr)

> +);
Sam Protsenko Dec. 4, 2019, 7:10 p.m. UTC | #8
Hi,

On Tue, Dec 3, 2019 at 9:29 PM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>
> Hi Sam,
> Cc: Aleksandr, Roman
>
> As expressed in the attached e-mail, to minimize the headaches extending
> the argument list of "bootimg" in future, can we please agree on below?
>
> On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > +U_BOOT_CMD(
> > +     bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> > +     "manipulate Android Boot Image",
> > +     "set_addr <addr>\n"
> > +     "    - set the address in RAM where boot image is located\n"
> > +     "      ($loadaddr is used by default)\n"
> > +     "bootimg ver <varname>\n"
>
> Can we make <varname> optional, with the background provided in [1]?
>

Already done in v3 (will send soon).

> > +     "    - get header version\n"
> > +     "bootimg get_dtbo <addr_var> [size_var]\n"
>
> How about converting <addr_var> to an optional argument too?
>

Already done in v3.

> > +     "    - get address and size (hex) of recovery DTBO area in the image\n"
> > +     "      <addr_var>: variable name to contain DTBO area address\n"
> > +     "      [size_var]: variable name to contain DTBO area size\n"
> > +     "bootimg dtb_dump\n"
> > +     "    - print info for all files in DTB area\n"
> > +     "bootimg dtb_load_addr <varname>\n"
>
> Same as above w.r.t. <varname>.
>

Already done in v3.

> > +     "    - get load address (hex) of DTB\n"
> > +     "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
>
> How about converting <addr_var> to an optional argument too?

Already done in v3.

> How do you foresee getting a blob entry based on id=<i> and/or
> rev=<r>? Which of below is your favorite option?
>
>  - get_dtb_file <index> [--id=<i>] [--rev=<r>] [addr_var] [size_var]
>    where: - in case <i> and/or <r> are provided, <index> tells the
>             command to pick the N's entry in the selection filtered by
>             <i> and <r>
>           - in case neither <i> nor <r> is provided, <index>
>             behaves like in the current patch (selects a blob entry
>             found at absolute index value ${index} in the image)
>
>  - get_dtb_file [<index>|[--id=<i>|--rev=<r>]] [addr_var] [size_var]
>    To make it clear, some example commands would be:
>    - get_dtb_file <index>
>      => current behavior
>    - get_dtb_file --id=<i>
>      => get _first_ blob entry matching id value <i>
>    - get_dtb_file --rev=<r>
>      => get _first_ blob entry matching rev value <r>
>    - get_dtb_file --id=<i> --rev=<r>
>      => get _first_ blob entry matching id <i> _and_ rev=<r>
>    - get_dtb_file <index> --id=<i>
>    - get_dtb_file <index> --rev=<r>
>      => Wrong usage
>
>  - get_dtb_file  anything else?
>

I already came up with next usage:

    abootimg get_dtb_file index <num> [addr_var] [size_var]

It's already done in v3. Once your patch series is merged, I will add
next two sub-commands:

    abootimg get_dtb_file id    <num> [addr_var] [size_var]
    abootimg get_dtb_file rev   <num> [addr_var] [size_var]

This way it's extensible. Also please see my review for your patches,
esp. for patch 4/4, where I discuss similar matter in context of
'dtimg' command.

> I think it is crucial to agree on the above, since the very first
> revision of "bootimg"/"abootimg" may impose strict limitations on how
> the command can be extended in future.
>

All those are addressed in v3 now. Along with renaming: 'bootimg' -> 'abootimg'.

The only thing remains to be addressed is Kconfig/Makefile decisions
you mentioned. Will look into that tomorrow, and either make it as you
pointed out or explain why it's good as it is.

> [just noticed your reply shedding more light on a subset of these
> questions, but still sending this out; please skip if already answered]
>
> > +     "    - get address and size (hex) of DTB file in the image\n"
> > +     "      <index>: index of desired DTB file in DTB area\n"
> > +     "      <addr_var>: variable name to contain DTB file address\n"
> > +     "      [size_var]: variable name to contain DTB file size\n"
> > +);
>
> [1] https://patchwork.ozlabs.org/patch/1202579/
>     ("cmd: dtimg: Make <varname> an optional argument")
>
> --
> Best Regards,
> Eugeniu
Sam Protsenko Dec. 4, 2019, 7:11 p.m. UTC | #9
Hi,

On Wed, Dec 4, 2019 at 7:33 PM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>
> Hello Sam,
> Please, see one more suggestion below.
>
> On Tue, Dec 03, 2019 at 08:29:10PM +0100, Eugeniu Rosca wrote:
> > Hi Sam,
> > Cc: Aleksandr, Roman
> >
> > As expressed in the attached e-mail, to minimize the headaches extending
> > the argument list of "bootimg" in future, can we please agree on below?
> >
> > On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > > +U_BOOT_CMD(
> > > +   bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> > > +   "manipulate Android Boot Image",
> > > +   "set_addr <addr>\n"
> > > +   "    - set the address in RAM where boot image is located\n"
> > > +   "      ($loadaddr is used by default)\n"
> > > +   "bootimg ver <varname>\n"
> >
> > Can we make <varname> optional, with the background provided in [1]?
> >
> > > +   "    - get header version\n"
> > > +   "bootimg get_dtbo <addr_var> [size_var]\n"
> >
> > How about converting <addr_var> to an optional argument too?
> >
> > > +   "    - get address and size (hex) of recovery DTBO area in the image\n"
> > > +   "      <addr_var>: variable name to contain DTBO area address\n"
> > > +   "      [size_var]: variable name to contain DTBO area size\n"
> > > +   "bootimg dtb_dump\n"
> > > +   "    - print info for all files in DTB area\n"
> > > +   "bootimg dtb_load_addr <varname>\n"
> >
> > Same as above w.r.t. <varname>.
> >
> > > +   "    - get load address (hex) of DTB\n"
> > > +   "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
>
> How about "get_dte" or "get_dtbe" instead of "get_dtb_file" ?
> It's shorter and should be easier to remember (dt{b}e = DT{B} Entry).
>

Sorry, I like get_dtb more. It's .dtb file in the end, and it's called
exactly "dtb" in boot.img struct. So this is a keeper :)

> --
> Best Regards,
> Eugeniu
Sam Protsenko Dec. 4, 2019, 7:23 p.m. UTC | #10
Hi,

On Wed, Dec 4, 2019 at 8:25 PM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>
> Hi again,
>
> [I would be willing to take this discussion offline, if you consider it
> too noisy for ML]
>

Agreed. Please find me on freenode IRC, nick: joeskb7. There is
#u-boot channel, or #linaro-android, whichever suits you best.

> On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > +U_BOOT_CMD(
> > +     bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> > +     "manipulate Android Boot Image",
> > +     "set_addr <addr>\n"
> > +     "    - set the address in RAM where boot image is located\n"
> > +     "      ($loadaddr is used by default)\n"
> > +     "bootimg ver <varname>\n"
> > +     "    - get header version\n"
> > +     "bootimg get_dtbo <addr_var> [size_var]\n"
> > +     "    - get address and size (hex) of recovery DTBO area in the image\n"
> > +     "      <addr_var>: variable name to contain DTBO area address\n"
> > +     "      [size_var]: variable name to contain DTBO area size\n"
> > +     "bootimg dtb_dump\n"
> > +     "    - print info for all files in DTB area\n"
>
> I now see that "DTBO area" is used intermixed with "DTB area".
> I think it makes sense to use one of the two consistently and drop the
> other. Otherwise, users might think there are two distinct areas in
> the same Android image.
>

Those are, in fact, two different areas in boot.img. "DTBO area" is a
payload in boot.img where recovery dtbo file can be placed. "DTB area"
is a payload in boot.img where DTB files can be placed (either
concatenated or wrapped into DTBO image format).

> > +     "bootimg dtb_load_addr <varname>\n"
> > +     "    - get load address (hex) of DTB\n"
>
> This is actually not something retrieved from the DTB/DTBO area, but
> from the "dtb_addr" field of the Android Image itself, as defined in
> https://android.googlesource.com/platform/system/tools/mkbootimg/+/refs/heads/master/include/bootimg/bootimg.h
>
> I think this little bit of information is essential, but not sure how to
> make it more transparent to the user, since purely based on the
> available help message, I tend to infer that there is connection between
> "DTB" in "get load address (hex) of DTB" and the "DTBO area", while
> there is no connection whatsoever.
>

Let's keep command usage length reasonable. We are bloating U-Boot
footprint too much as it is already... I think user shouldn't care
where the load address is obtained from, really. Prefer to keep it
short, as it is.

> > +     "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
> > +     "    - get address and size (hex) of DTB file in the image\n"
> > +     "      <index>: index of desired DTB file in DTB area\n"
> > +     "      <addr_var>: variable name to contain DTB file address\n"
> > +     "      [size_var]: variable name to contain DTB file size\n"
>
> Would it make more sense to use "DTB entry" instead of "DTB file"
> since this is the wording used in the Google spec/header?
>

I'd argue that "DTB file" is more clear for user, than "entry". If you
don't have a strong preference on this one, let's keep it as is.

> Another general comment regarding the current sub-commands:
>  - set_addr
>  - ver
>  - get_dtbo
>  - dtb_dump
>  - dtb_load_addr
>  - get_dtb_file
>
> I observe the following (inconsistent) pattern:
>  - <do>_<what>
>  - <what>
>  - <do>_<what>
>  - <what>_<do>
>  - <what>_<do>_<what>
>  - <do>_<what>
>
> Looking at the "fdt" command, I find its sub-commands
> somehow better partitioned and easier to digest/remember:
>
> fdt addr [-c]  <addr> [<length>]
> fdt apply <addr>
> fdt move   <fdt> <newaddr> <length>
> fdt resize [<extrasize>]
> fdt print  <path> [<prop>]
> fdt list   <path> [<prop>]
> fdt get value <var> <path> <prop>
> fdt get name <var> <path> <index>
> fdt get addr <var> <path> <prop>
> fdt get size <var> <path> [<prop>]
> fdt set    <path> <prop> [<val>]
> fdt mknode <path> <node>
> fdt rm     <path> [<prop>]
> fdt header [get <var> <member>]
>
> Its syntax seems to be:
>  <command> <do> <what> [options]
>
> Would it make sense to borrow this naming style/principle?
> It could translate to the following for abootimg:
>
> abootimg (current sub-command name enclosed in brackets):
>  - addr (set_addr)
>  - ver
>  - dump dtbo (dtb_dump)
>  - get dtbo (get_dtbo)
>  - get dtbe (get_dtb_file)
>  - get dtla (dtb_load_addr)
>

Makes sense. I'll think about it.

Thanks for review!

> > +);
>
> --
> Best Regards,
> Eugeniu
Aleksandr Bulyshchenko Dec. 5, 2019, 2:17 a.m. UTC | #11
Hello Sam,

I'd like to add my 5 cents regarding separating dtimg start|size into 3
subcommands

> dtimg start index <num> <addr> [varname]
> dtimg start id <num> <addr> [varname]
> dtimg start rev <num> <addr> [varname]
>
> While I don't see real usecases for combining index with id or rev (if
someone applies metainformation to dtb entries for meaningful lookup,
identical entries most probably mean copy-paste error),
but at the same time I see space for at least two-factor identification
(e.g. model and revision).
Thus API should allow (but not require) combining id and rev.

The same remains relevant for abootimg as well.

Thanks,
Aleksandr Bulyshchenko

On Wed, Dec 4, 2019 at 9:12 PM Sam Protsenko <semen.protsenko@linaro.org>
wrote:

> Hi,
>
> On Wed, Dec 4, 2019 at 7:33 PM Eugeniu Rosca <erosca@de.adit-jv.com>
> wrote:
> >
> > Hello Sam,
> > Please, see one more suggestion below.
> >
> > On Tue, Dec 03, 2019 at 08:29:10PM +0100, Eugeniu Rosca wrote:
> > > Hi Sam,
> > > Cc: Aleksandr, Roman
> > >
> > > As expressed in the attached e-mail, to minimize the headaches
> extending
> > > the argument list of "bootimg" in future, can we please agree on below?
> > >
> > > On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
> > > > +U_BOOT_CMD(
> > > > +   bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
> > > > +   "manipulate Android Boot Image",
> > > > +   "set_addr <addr>\n"
> > > > +   "    - set the address in RAM where boot image is located\n"
> > > > +   "      ($loadaddr is used by default)\n"
> > > > +   "bootimg ver <varname>\n"
> > >
> > > Can we make <varname> optional, with the background provided in [1]?
> > >
> > > > +   "    - get header version\n"
> > > > +   "bootimg get_dtbo <addr_var> [size_var]\n"
> > >
> > > How about converting <addr_var> to an optional argument too?
> > >
> > > > +   "    - get address and size (hex) of recovery DTBO area in the
> image\n"
> > > > +   "      <addr_var>: variable name to contain DTBO area address\n"
> > > > +   "      [size_var]: variable name to contain DTBO area size\n"
> > > > +   "bootimg dtb_dump\n"
> > > > +   "    - print info for all files in DTB area\n"
> > > > +   "bootimg dtb_load_addr <varname>\n"
> > >
> > > Same as above w.r.t. <varname>.
> > >
> > > > +   "    - get load address (hex) of DTB\n"
> > > > +   "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
> >
> > How about "get_dte" or "get_dtbe" instead of "get_dtb_file" ?
> > It's shorter and should be easier to remember (dt{b}e = DT{B} Entry).
> >
>
> Sorry, I like get_dtb more. It's .dtb file in the end, and it's called
> exactly "dtb" in boot.img struct. So this is a keeper :)
>
> > --
> > Best Regards,
> > Eugeniu
>
Eugeniu Rosca Dec. 5, 2019, 10:36 a.m. UTC | #12
On Thu, Dec 05, 2019 at 04:17:38AM +0200, Aleksandr Bulyshchenko wrote:
>    Hello Sam,
>    I'd like to add my 5 cents regarding separating dtimg start|size into 3
>    subcommands
> 
>  dtimg start index <num> <addr> [varname]
>  dtimg start id <num> <addr> [varname]
>  dtimg start rev <num> <addr> [varname]
> 
>    While I don't see real usecases for combining index with id or rev (if
>    someone applies metainformation to dtb entries for meaningful lookup,
>    identical entries most probably mean copy-paste error),
>    but at the same time I see space for at least two-factor identification
>    (e.g. model and revision).
>    Thus API should allow (but not require) combining id and rev.
>    The same remains relevant for abootimg as well.

[shameless plug] Agreed with Aleksandr. Users will want to provide <id>
and <rev> (and possibly cust[0-4] in future) in one go/command launch.
Sam Protsenko Dec. 5, 2019, 1:58 p.m. UTC | #13
Hi Aleksandr,

On Thu, Dec 5, 2019 at 4:17 AM Aleksandr Bulyshchenko
<a.bulyshchenko@globallogic.com> wrote:
>
> Hello Sam,
>
> I'd like to add my 5 cents regarding separating dtimg start|size into 3 subcommands
>>
>> dtimg start index <num> <addr> [varname]
>> dtimg start id <num> <addr> [varname]
>> dtimg start rev <num> <addr> [varname]
>
> While I don't see real usecases for combining index with id or rev (if someone applies metainformation to dtb entries for meaningful lookup, identical entries most probably mean copy-paste error),
> but at the same time I see space for at least two-factor identification (e.g. model and revision).
> Thus API should allow (but not require) combining id and rev.
>

Agreed on id+rev usage. Can we still try and keep the interface as
simple as possible, e.g. like this:

    dtimg start index <num> <addr> [varname]
    dtimg start id <id_num> <rev_num> <custom_num> <addr> [varname]

In case when user wants to use only "id" or only  "rev", other bit
should be specified as "-":

    dtimg start id 10 - - <addr> [varname]
    dtimg start id - 10 - <addr> [varname]

It's similar to what is done in 'bootm' command:

    To boot that kernel without an initrd image,use a '-' for the
second argument.

This way we can keep away the 'index' usage, making two things possible:
  1. Code will be easier (we can provide one function for 'index' case
and one function for 'id/rev/custom' case)
  2. Easier for us to split the work and avoid dependencies between
our patch series

If everyone agrees on usage I suggested above, we can go ahead and
change it correspondingly for 'dtimg' and 'abootimg' patch series.

> The same remains relevant for abootimg as well.
>
> Thanks,
> Aleksandr Bulyshchenko
>
> On Wed, Dec 4, 2019 at 9:12 PM Sam Protsenko <semen.protsenko@linaro.org> wrote:
>>
>> Hi,
>>
>> On Wed, Dec 4, 2019 at 7:33 PM Eugeniu Rosca <erosca@de.adit-jv.com> wrote:
>> >
>> > Hello Sam,
>> > Please, see one more suggestion below.
>> >
>> > On Tue, Dec 03, 2019 at 08:29:10PM +0100, Eugeniu Rosca wrote:
>> > > Hi Sam,
>> > > Cc: Aleksandr, Roman
>> > >
>> > > As expressed in the attached e-mail, to minimize the headaches extending
>> > > the argument list of "bootimg" in future, can we please agree on below?
>> > >
>> > > On Wed, Oct 23, 2019 at 05:34:22PM +0300, Sam Protsenko wrote:
>> > > > +U_BOOT_CMD(
>> > > > +   bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
>> > > > +   "manipulate Android Boot Image",
>> > > > +   "set_addr <addr>\n"
>> > > > +   "    - set the address in RAM where boot image is located\n"
>> > > > +   "      ($loadaddr is used by default)\n"
>> > > > +   "bootimg ver <varname>\n"
>> > >
>> > > Can we make <varname> optional, with the background provided in [1]?
>> > >
>> > > > +   "    - get header version\n"
>> > > > +   "bootimg get_dtbo <addr_var> [size_var]\n"
>> > >
>> > > How about converting <addr_var> to an optional argument too?
>> > >
>> > > > +   "    - get address and size (hex) of recovery DTBO area in the image\n"
>> > > > +   "      <addr_var>: variable name to contain DTBO area address\n"
>> > > > +   "      [size_var]: variable name to contain DTBO area size\n"
>> > > > +   "bootimg dtb_dump\n"
>> > > > +   "    - print info for all files in DTB area\n"
>> > > > +   "bootimg dtb_load_addr <varname>\n"
>> > >
>> > > Same as above w.r.t. <varname>.
>> > >
>> > > > +   "    - get load address (hex) of DTB\n"
>> > > > +   "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
>> >
>> > How about "get_dte" or "get_dtbe" instead of "get_dtb_file" ?
>> > It's shorter and should be easier to remember (dt{b}e = DT{B} Entry).
>> >
>>
>> Sorry, I like get_dtb more. It's .dtb file in the end, and it's called
>> exactly "dtb" in boot.img struct. So this is a keeper :)
>>
>> > --
>> > Best Regards,
>> > Eugeniu
diff mbox series

Patch

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07060c63a7..d89a91cde4 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -356,6 +356,14 @@  config CMD_DTIMG
 	  files should be merged in one dtb further, which needs to be passed to
 	  the kernel, as part of a boot process.
 
+config CMD_BOOTIMG
+	bool "bootimg"
+	depends on ANDROID_BOOT_IMAGE
+	help
+	  Android Boot Image manipulation commands. Allows one to extract
+	  images contained in boot.img, like kernel, ramdisk, dtb, etc, and
+	  obtain corresponding meta-information from boot.img.
+
 config CMD_ELF
 	bool "bootelf, bootvx"
 	default y
diff --git a/cmd/Makefile b/cmd/Makefile
index ac843b4b16..bf15e38f41 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -48,6 +48,7 @@  ifdef CONFIG_POST
 obj-$(CONFIG_CMD_DIAG) += diag.o
 endif
 obj-$(CONFIG_CMD_DTIMG) += dtimg.o
+obj-$(CONFIG_CMD_BOOTIMG) += bootimg.o
 obj-$(CONFIG_CMD_ECHO) += echo.o
 obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
 obj-$(CONFIG_CMD_EEPROM) += eeprom.o
diff --git a/cmd/bootimg.c b/cmd/bootimg.c
new file mode 100644
index 0000000000..a26a74f124
--- /dev/null
+++ b/cmd/bootimg.c
@@ -0,0 +1,210 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko@linaro.org>
+ */
+
+#include <android_image.h>
+#include <common.h>
+#include <mapmem.h>
+
+#define bootimg_addr() (_bootimg_addr == -1 ? load_addr : _bootimg_addr)
+
+/* Please use bootimg_addr() macro to obtain the boot image address */
+static ulong _bootimg_addr = -1;
+
+static int do_bootimg_set_addr(cmd_tbl_t *cmdtp, int flag, int argc,
+			       char * const argv[])
+{
+	char *endp;
+	ulong img_addr;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	img_addr = simple_strtoul(argv[1], &endp, 16);
+	if (*endp != '\0') {
+		printf("Error: Wrong image address\n");
+		return CMD_RET_FAILURE;
+	}
+
+	_bootimg_addr = img_addr;
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_ver(cmd_tbl_t *cmdtp, int flag, int argc,
+			  char * const argv[])
+{
+	const struct andr_img_hdr *hdr;
+	char buf[65];
+	int res = CMD_RET_SUCCESS;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	hdr = map_sysmem(bootimg_addr(), sizeof(*hdr));
+	if (android_image_check_header(hdr)) {
+		printf("Error: Boot Image header is incorrect\n");
+		res = CMD_RET_FAILURE;
+		goto exit;
+	}
+
+	snprintf(buf, sizeof(buf), "%u", hdr->header_version);
+	env_set(argv[1], buf);
+
+exit:
+	unmap_sysmem(hdr);
+	return res;
+}
+
+static int do_bootimg_get_dtbo(cmd_tbl_t *cmdtp, int flag, int argc,
+			       char * const argv[])
+{
+	char buf[65];
+	ulong addr;
+	u32 size;
+
+	if (argc < 2 || argc > 3)
+		return CMD_RET_USAGE;
+
+	if (!android_image_get_dtbo(bootimg_addr(), &addr, &size))
+		return CMD_RET_FAILURE;
+
+	snprintf(buf, sizeof(buf), "%lx", addr);
+	env_set(argv[1], buf);
+
+	if (argc == 3) {
+		snprintf(buf, sizeof(buf), "%x", size);
+		env_set(argv[2], buf);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_dtb_dump(cmd_tbl_t *cmdtp, int flag, int argc,
+			       char * const argv[])
+{
+	if (argc != 1)
+		return CMD_RET_USAGE;
+
+	if (android_image_print_dtb_contents(bootimg_addr()))
+		return CMD_RET_FAILURE;
+
+	return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_dtb_load_addr(cmd_tbl_t *cmdtp, int flag, int argc,
+				    char * const argv[])
+{
+	const struct andr_img_hdr *hdr;
+	char buf[65];
+	int res = CMD_RET_SUCCESS;
+
+	if (argc != 2)
+		return CMD_RET_USAGE;
+
+	hdr = map_sysmem(bootimg_addr(), sizeof(*hdr));
+	if (android_image_check_header(hdr)) {
+		printf("Error: Boot Image header is incorrect\n");
+		res = CMD_RET_FAILURE;
+		goto exit;
+	}
+
+	if (hdr->header_version < 2) {
+		printf("Error: header_version must be >= 2 for this\n");
+		res = CMD_RET_FAILURE;
+		goto exit;
+	}
+
+	snprintf(buf, sizeof(buf), "%lx", (ulong)hdr->dtb_addr);
+	env_set(argv[1], buf);
+
+exit:
+	unmap_sysmem(hdr);
+	return res;
+}
+
+static int do_bootimg_get_dtb_file(cmd_tbl_t *cmdtp, int flag, int argc,
+				   char * const argv[])
+{
+	char *endp;
+	char buf[65];
+	u32 index;
+	ulong addr;
+	u32 size;
+
+	if (argc < 3 || argc > 4)
+		return CMD_RET_USAGE;
+
+	index = simple_strtoul(argv[1], &endp, 0);
+	if (*endp != '\0') {
+		printf("Error: Wrong index\n");
+		return CMD_RET_FAILURE;
+	}
+
+	if (!android_image_get_dtb_by_index(bootimg_addr(), index, &addr,
+					    &size))
+		return CMD_RET_FAILURE;
+
+	snprintf(buf, sizeof(buf), "%lx", addr);
+	env_set(argv[2], buf);
+
+	if (argc == 4) {
+		snprintf(buf, sizeof(buf), "%x", size);
+		env_set(argv[3], buf);
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_bootimg_sub[] = {
+	U_BOOT_CMD_MKENT(set_addr, 2, 1, do_bootimg_set_addr, "", ""),
+	U_BOOT_CMD_MKENT(ver, 2, 1, do_bootimg_ver, "", ""),
+	U_BOOT_CMD_MKENT(get_dtbo, 3, 1, do_bootimg_get_dtbo, "", ""),
+	U_BOOT_CMD_MKENT(dtb_dump, 1, 1, do_bootimg_dtb_dump, "", ""),
+	U_BOOT_CMD_MKENT(dtb_load_addr, 2, 1, do_bootimg_dtb_load_addr, "", ""),
+	U_BOOT_CMD_MKENT(get_dtb_file, 4, 1, do_bootimg_get_dtb_file, "", ""),
+};
+
+static int do_bootimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	cmd_tbl_t *cp;
+
+	cp = find_cmd_tbl(argv[1], cmd_bootimg_sub,
+			  ARRAY_SIZE(cmd_bootimg_sub));
+
+	/* Strip off leading 'bootimg' command argument */
+	argc--;
+	argv++;
+
+	if (!cp || argc > cp->maxargs)
+		return CMD_RET_USAGE;
+	if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+		return CMD_RET_SUCCESS;
+
+	return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+	bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
+	"manipulate Android Boot Image",
+	"set_addr <addr>\n"
+	"    - set the address in RAM where boot image is located\n"
+	"      ($loadaddr is used by default)\n"
+	"bootimg ver <varname>\n"
+	"    - get header version\n"
+	"bootimg get_dtbo <addr_var> [size_var]\n"
+	"    - get address and size (hex) of recovery DTBO area in the image\n"
+	"      <addr_var>: variable name to contain DTBO area address\n"
+	"      [size_var]: variable name to contain DTBO area size\n"
+	"bootimg dtb_dump\n"
+	"    - print info for all files in DTB area\n"
+	"bootimg dtb_load_addr <varname>\n"
+	"    - get load address (hex) of DTB\n"
+	"bootimg get_dtb_file <index> <addr_var> [size_var]\n"
+	"    - get address and size (hex) of DTB file in the image\n"
+	"      <index>: index of desired DTB file in DTB area\n"
+	"      <addr_var>: variable name to contain DTB file address\n"
+	"      [size_var]: variable name to contain DTB file size\n"
+);