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