uboot/cmd/adtimg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2018 Linaro Ltd.
   4 * Sam Protsenko <semen.protsenko@linaro.org>
   5 * Eugeniu Rosca <rosca.eugeniu@gmail.com>
   6 */
   7
   8#include <command.h>
   9#include <env.h>
  10#include <image-android-dt.h>
  11#include <common.h>
  12
  13#define OPT_INDEX       "--index"
  14
  15/*
  16 * Current/working DTB/DTBO Android image address.
  17 * Similar to 'working_fdt' variable in 'fdt' command.
  18 */
  19static ulong working_img;
  20
  21static int do_adtimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
  22                          char *const argv[])
  23{
  24        char *endp;
  25        ulong hdr_addr;
  26
  27        if (argc != 2)
  28                return CMD_RET_USAGE;
  29
  30        hdr_addr = hextoul(argv[1], &endp);
  31        if (*endp != '\0') {
  32                printf("Error: Wrong image address '%s'\n", argv[1]);
  33                return CMD_RET_FAILURE;
  34        }
  35
  36        /*
  37         * Allow users to set an address prior to copying the DTB/DTBO
  38         * image to that same address, i.e. skip header verification.
  39         */
  40
  41        working_img = hdr_addr;
  42        return CMD_RET_SUCCESS;
  43}
  44
  45static int adtimg_check_working_img(void)
  46{
  47        if (!working_img) {
  48                printf("Error: Please, call 'adtimg addr <addr>'. Aborting!\n");
  49                return CMD_RET_FAILURE;
  50        }
  51
  52        if (!android_dt_check_header(working_img)) {
  53                printf("Error: Invalid image header at 0x%lx\n", working_img);
  54                return CMD_RET_FAILURE;
  55        }
  56
  57        return CMD_RET_SUCCESS;
  58}
  59
  60static int do_adtimg_dump(struct cmd_tbl *cmdtp, int flag, int argc,
  61                          char *const argv[])
  62{
  63        if (argc != 1)
  64                return CMD_RET_USAGE;
  65
  66        if (adtimg_check_working_img() != CMD_RET_SUCCESS)
  67                return CMD_RET_FAILURE;
  68
  69        android_dt_print_contents(working_img);
  70
  71        return CMD_RET_SUCCESS;
  72}
  73
  74static int adtimg_getopt_u32(char * const opt, char * const name, u32 *optval)
  75{
  76        char *endp, *str;
  77        u32 val;
  78
  79        if (!opt || !name || !optval)
  80                return CMD_RET_FAILURE;
  81
  82        str = strchr(opt, '=');
  83        if (!str) {
  84                printf("Error: Option '%s' not followed by '='\n", name);
  85                return CMD_RET_FAILURE;
  86        }
  87
  88        if (*++str == '\0') {
  89                printf("Error: Option '%s=' not followed by value\n", name);
  90                return CMD_RET_FAILURE;
  91        }
  92
  93        val = simple_strtoul(str, &endp, 0);
  94        if (*endp != '\0') {
  95                printf("Error: Wrong integer value '%s=%s'\n", name, str);
  96                return CMD_RET_FAILURE;
  97        }
  98
  99        *optval = val;
 100        return CMD_RET_SUCCESS;
 101}
 102
 103static int adtimg_getopt_index(int argc, char *const argv[], u32 *index,
 104                               char **avar, char **svar)
 105{
 106        int ret;
 107
 108        if (!argv || !avar || !svar)
 109                return CMD_RET_FAILURE;
 110
 111        if (argc > 3) {
 112                printf("Error: Unexpected argument '%s'\n", argv[3]);
 113                return CMD_RET_FAILURE;
 114        }
 115
 116        ret = adtimg_getopt_u32(argv[0], OPT_INDEX, index);
 117        if (ret != CMD_RET_SUCCESS)
 118                return ret;
 119
 120        if (argc > 1)
 121                *avar = argv[1];
 122        if (argc > 2)
 123                *svar = argv[2];
 124
 125        return CMD_RET_SUCCESS;
 126}
 127
 128static int adtimg_get_dt_by_index(int argc, char *const argv[])
 129{
 130        ulong addr;
 131        u32 index, size;
 132        int ret;
 133        char *avar = NULL, *svar = NULL;
 134
 135        ret = adtimg_getopt_index(argc, argv, &index, &avar, &svar);
 136        if (ret != CMD_RET_SUCCESS)
 137                return ret;
 138
 139        if (!android_dt_get_fdt_by_index(working_img, index, &addr, &size))
 140                return CMD_RET_FAILURE;
 141
 142        if (avar && svar) {
 143                ret = env_set_hex(avar, addr);
 144                if (ret) {
 145                        printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
 146                        return CMD_RET_FAILURE;
 147                }
 148                ret = env_set_hex(svar, size);
 149                if (ret) {
 150                        printf("Error: Can't set '%s' to 0x%x\n", svar, size);
 151                        return CMD_RET_FAILURE;
 152                }
 153        } else if (avar) {
 154                ret = env_set_hex(avar, addr);
 155                if (ret) {
 156                        printf("Error: Can't set '%s' to 0x%lx\n", avar, addr);
 157                        return CMD_RET_FAILURE;
 158                }
 159                printf("0x%x (%d)\n", size, size);
 160        } else {
 161                printf("0x%lx, 0x%x (%d)\n", addr, size, size);
 162        }
 163
 164        return CMD_RET_SUCCESS;
 165}
 166
 167static int adtimg_get_dt(int argc, char *const argv[])
 168{
 169        if (argc < 2) {
 170                printf("Error: No options passed to '%s'\n", argv[0]);
 171                return CMD_RET_FAILURE;
 172        }
 173
 174        /* Strip off leading 'dt' command argument */
 175        argc--;
 176        argv++;
 177
 178        if (!strncmp(argv[0], OPT_INDEX, sizeof(OPT_INDEX) - 1))
 179                return adtimg_get_dt_by_index(argc, argv);
 180
 181        printf("Error: Option '%s' not supported\n", argv[0]);
 182        return CMD_RET_FAILURE;
 183}
 184
 185static int do_adtimg_get(struct cmd_tbl *cmdtp, int flag, int argc,
 186                         char *const argv[])
 187{
 188        if (argc < 2) {
 189                printf("Error: No arguments passed to '%s'\n", argv[0]);
 190                return CMD_RET_FAILURE;
 191        }
 192
 193        if (adtimg_check_working_img() != CMD_RET_SUCCESS)
 194                return CMD_RET_FAILURE;
 195
 196        /* Strip off leading 'get' command argument */
 197        argc--;
 198        argv++;
 199
 200        if (!strcmp(argv[0], "dt"))
 201                return adtimg_get_dt(argc, argv);
 202
 203        printf("Error: Wrong argument '%s'\n", argv[0]);
 204        return CMD_RET_FAILURE;
 205}
 206
 207static struct cmd_tbl cmd_adtimg_sub[] = {
 208        U_BOOT_CMD_MKENT(addr, CONFIG_SYS_MAXARGS, 1, do_adtimg_addr, "", ""),
 209        U_BOOT_CMD_MKENT(dump, CONFIG_SYS_MAXARGS, 1, do_adtimg_dump, "", ""),
 210        U_BOOT_CMD_MKENT(get, CONFIG_SYS_MAXARGS, 1, do_adtimg_get, "", ""),
 211};
 212
 213static int do_adtimg(struct cmd_tbl *cmdtp, int flag, int argc,
 214                     char *const argv[])
 215{
 216        struct cmd_tbl *cp;
 217
 218        cp = find_cmd_tbl(argv[1], cmd_adtimg_sub, ARRAY_SIZE(cmd_adtimg_sub));
 219
 220        /* Strip off leading 'adtimg' command argument */
 221        argc--;
 222        argv++;
 223
 224        if (!cp || argc > cp->maxargs)
 225                return CMD_RET_USAGE;
 226        if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
 227                return CMD_RET_SUCCESS;
 228
 229        return cp->cmd(cmdtp, flag, argc, argv);
 230}
 231
 232U_BOOT_CMD(
 233        adtimg, CONFIG_SYS_MAXARGS, 0, do_adtimg,
 234        "manipulate dtb/dtbo Android image",
 235        "addr <addr> - Set image location to <addr>\n"
 236        "adtimg dump        - Print out image contents\n"
 237        "adtimg get dt --index=<index> [avar [svar]]         - Get DT address/size by index\n"
 238        "\n"
 239        "Legend:\n"
 240        "  - <addr>: DTB/DTBO image address (hex) in RAM\n"
 241        "  - <index>: index (hex/dec) of desired DT in the image\n"
 242        "  - <avar>: variable name to contain DT address (hex)\n"
 243        "  - <svar>: variable name to contain DT size (hex)"
 244);
 245