Home | History | Annotate | Download | only in fastboot
      1 // SPDX-License-Identifier: BSD-2-Clause
      2 /*
      3  * Copyright (C) 2016 The Android Open Source Project
      4  */
      5 
      6 #include <common.h>
      7 #include <fastboot.h>
      8 #include <fastboot-internal.h>
      9 #include <fb_mmc.h>
     10 #include <fb_nand.h>
     11 #include <fs.h>
     12 #include <version.h>
     13 
     14 static void getvar_version(char *var_parameter, char *response);
     15 static void getvar_bootloader_version(char *var_parameter, char *response);
     16 static void getvar_downloadsize(char *var_parameter, char *response);
     17 static void getvar_serialno(char *var_parameter, char *response);
     18 static void getvar_version_baseband(char *var_parameter, char *response);
     19 static void getvar_product(char *var_parameter, char *response);
     20 static void getvar_current_slot(char *var_parameter, char *response);
     21 static void getvar_slot_suffixes(char *var_parameter, char *response);
     22 static void getvar_has_slot(char *var_parameter, char *response);
     23 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
     24 static void getvar_partition_type(char *part_name, char *response);
     25 #endif
     26 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
     27 static void getvar_partition_size(char *part_name, char *response);
     28 #endif
     29 
     30 static const struct {
     31 	const char *variable;
     32 	void (*dispatch)(char *var_parameter, char *response);
     33 } getvar_dispatch[] = {
     34 	{
     35 		.variable = "version",
     36 		.dispatch = getvar_version
     37 	}, {
     38 		.variable = "bootloader-version",
     39 		.dispatch = getvar_bootloader_version
     40 	}, {
     41 		.variable = "version-bootloader",
     42 		.dispatch = getvar_bootloader_version
     43 	}, {
     44 		.variable = "downloadsize",
     45 		.dispatch = getvar_downloadsize
     46 	}, {
     47 		.variable = "max-download-size",
     48 		.dispatch = getvar_downloadsize
     49 	}, {
     50 		.variable = "serialno",
     51 		.dispatch = getvar_serialno
     52 	}, {
     53 		.variable = "version-baseband",
     54 		.dispatch = getvar_version_baseband
     55 	}, {
     56 		.variable = "product",
     57 		.dispatch = getvar_product
     58 	}, {
     59 		.variable = "current-slot",
     60 		.dispatch = getvar_current_slot
     61 	}, {
     62 		.variable = "slot-suffixes",
     63 		.dispatch = getvar_slot_suffixes
     64 	}, {
     65 		.variable = "has_slot",
     66 		.dispatch = getvar_has_slot
     67 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
     68 	}, {
     69 		.variable = "partition-type",
     70 		.dispatch = getvar_partition_type
     71 #endif
     72 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
     73 	}, {
     74 		.variable = "partition-size",
     75 		.dispatch = getvar_partition_size
     76 #endif
     77 	}
     78 };
     79 
     80 static void getvar_version(char *var_parameter, char *response)
     81 {
     82 	fastboot_okay(FASTBOOT_VERSION, response);
     83 }
     84 
     85 static void getvar_bootloader_version(char *var_parameter, char *response)
     86 {
     87 	fastboot_okay(U_BOOT_VERSION, response);
     88 }
     89 
     90 static void getvar_downloadsize(char *var_parameter, char *response)
     91 {
     92 	fastboot_response("OKAY", response, "0x%08x", fastboot_buf_size);
     93 }
     94 
     95 static void getvar_serialno(char *var_parameter, char *response)
     96 {
     97 	const char *tmp = env_get("serial#");
     98 
     99 	if (tmp)
    100 		fastboot_okay(tmp, response);
    101 	else
    102 		fastboot_fail("Value not set", response);
    103 }
    104 
    105 static void getvar_version_baseband(char *var_parameter, char *response)
    106 {
    107 	fastboot_okay("N/A", response);
    108 }
    109 
    110 static void getvar_product(char *var_parameter, char *response)
    111 {
    112 	const char *board = env_get("board");
    113 
    114 	if (board)
    115 		fastboot_okay(board, response);
    116 	else
    117 		fastboot_fail("Board not set", response);
    118 }
    119 
    120 static void getvar_current_slot(char *var_parameter, char *response)
    121 {
    122 	/* A/B not implemented, for now always return _a */
    123 	fastboot_okay("_a", response);
    124 }
    125 
    126 static void getvar_slot_suffixes(char *var_parameter, char *response)
    127 {
    128 	fastboot_okay("_a,_b", response);
    129 }
    130 
    131 static void getvar_has_slot(char *part_name, char *response)
    132 {
    133 	if (part_name && (!strcmp(part_name, "boot") ||
    134 			  !strcmp(part_name, "system")))
    135 		fastboot_okay("yes", response);
    136 	else
    137 		fastboot_okay("no", response);
    138 }
    139 
    140 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
    141 static void getvar_partition_type(char *part_name, char *response)
    142 {
    143 	int r;
    144 	struct blk_desc *dev_desc;
    145 	disk_partition_t part_info;
    146 
    147 	r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
    148 				       response);
    149 	if (r >= 0) {
    150 		r = fs_set_blk_dev_with_part(dev_desc, r);
    151 		if (r < 0)
    152 			fastboot_fail("failed to set partition", response);
    153 		else
    154 			fastboot_okay(fs_get_type_name(), response);
    155 	}
    156 }
    157 #endif
    158 
    159 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH)
    160 static void getvar_partition_size(char *part_name, char *response)
    161 {
    162 	int r;
    163 	size_t size;
    164 
    165 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_MMC)
    166 	struct blk_desc *dev_desc;
    167 	disk_partition_t part_info;
    168 
    169 	r = fastboot_mmc_get_part_info(part_name, &dev_desc, &part_info,
    170 				       response);
    171 	if (r >= 0)
    172 		size = part_info.size;
    173 #endif
    174 #if CONFIG_IS_ENABLED(FASTBOOT_FLASH_NAND)
    175 	struct part_info *part_info;
    176 
    177 	r = fastboot_nand_get_part_info(part_name, &part_info, response);
    178 	if (r >= 0)
    179 		size = part_info->size;
    180 #endif
    181 	if (r >= 0)
    182 		fastboot_response("OKAY", response, "0x%016zx", size);
    183 }
    184 #endif
    185 
    186 /**
    187  * fastboot_getvar() - Writes variable indicated by cmd_parameter to response.
    188  *
    189  * @cmd_parameter: Pointer to command parameter
    190  * @response: Pointer to fastboot response buffer
    191  *
    192  * Look up cmd_parameter first as an environment variable of the form
    193  * fastboot.<cmd_parameter>, if that exists return use its value to set
    194  * response.
    195  *
    196  * Otherwise lookup the name of variable and execute the appropriate
    197  * function to return the requested value.
    198  */
    199 void fastboot_getvar(char *cmd_parameter, char *response)
    200 {
    201 	if (!cmd_parameter) {
    202 		fastboot_fail("missing var", response);
    203 	} else {
    204 #define FASTBOOT_ENV_PREFIX	"fastboot."
    205 		int i;
    206 		char *var_parameter = cmd_parameter;
    207 		char envstr[FASTBOOT_RESPONSE_LEN];
    208 		const char *s;
    209 
    210 		snprintf(envstr, sizeof(envstr) - 1,
    211 			 FASTBOOT_ENV_PREFIX "%s", cmd_parameter);
    212 		s = env_get(envstr);
    213 		if (s) {
    214 			fastboot_response("OKAY", response, "%s", s);
    215 			return;
    216 		}
    217 
    218 		strsep(&var_parameter, ":");
    219 		for (i = 0; i < ARRAY_SIZE(getvar_dispatch); ++i) {
    220 			if (!strcmp(getvar_dispatch[i].variable,
    221 				    cmd_parameter)) {
    222 				getvar_dispatch[i].dispatch(var_parameter,
    223 							    response);
    224 				return;
    225 			}
    226 		}
    227 		pr_warn("WARNING: unknown variable: %s\n", cmd_parameter);
    228 		fastboot_fail("Variable not implemented", response);
    229 	}
    230 }
    231