1 /* 2 * Copyright 2014 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <stdio.h> 19 #include <unistd.h> 20 #include <stdbool.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <fcntl.h> 26 #include <cutils/properties.h> 27 #include <sys/mman.h> 28 #include "fw_version_check.h" 29 #include "edify/expr.h" 30 31 #define FORCE_RW_OPT "0" 32 #define BOOT_IFWI_SIZE 0x400000 33 #define BOOT_UMIP_SIZE 0x10000 34 #define BOOT_UMIP_SECTOR_SIZE 0x200 35 #define BOOT_UMIP_XOR_OFFSET 0x7 36 #define BOOT_UMIP_3GPP_OFFSET 0x76F 37 #define BOOT_IFWI_XOR_OFFSET 0x0112d8 38 #define BOOT_DNX_TIMEOUT_OFFSET 0x400 39 #define IFWI_OFFSET 0 40 #define TOKEN_UMIP_AREA_OFFSET 0x4000 41 #define TOKEN_UMIP_AREA_SIZE 0x2C00 42 #define FILE_PATH_SIZE 64 43 #define IFWI_TYPE_LSH 12 44 45 static void dump_fw_versions(struct firmware_versions *v) 46 { 47 fprintf(stderr, "Image FW versions:\n"); 48 fprintf(stderr, " ifwi: %04X.%04X\n", v->ifwi.major, v->ifwi.minor); 49 fprintf(stderr, "---- components ----\n"); 50 fprintf(stderr, " scu: %04X.%04X\n", v->scu.major, v->scu.minor); 51 fprintf(stderr, " hooks/oem: %04X.%04X\n", v->valhooks.major, v->valhooks.minor); 52 fprintf(stderr, " ia32: %04X.%04X\n", v->ia32.major, v->ia32.minor); 53 fprintf(stderr, " chaabi: %04X.%04X\n", v->chaabi.major, v->chaabi.minor); 54 fprintf(stderr, " mIA: %04X.%04X\n", v->mia.major, v->mia.minor); 55 } 56 57 static int force_rw(const char *name) { 58 int ret, fd; 59 60 fd = open(name, O_WRONLY); 61 if (fd < 0) { 62 fprintf(stderr, "force_ro(): failed to open %s\n", name); 63 return fd; 64 } 65 66 ret = write(fd, FORCE_RW_OPT, sizeof(FORCE_RW_OPT)); 67 if (ret <= 0) { 68 fprintf(stderr, "force_ro(): failed to write %s\n", name); 69 close(fd); 70 return ret; 71 } 72 73 close(fd); 74 return 0; 75 } 76 77 int check_ifwi_file_scu_emmc(void *data, size_t size) 78 { 79 struct firmware_versions dev_fw_rev, img_fw_rev; 80 81 if (get_image_fw_rev(data, size, &img_fw_rev)) { 82 fprintf(stderr, "Coudn't extract FW version data from image\n"); 83 return -1; 84 } 85 86 dump_fw_versions(&img_fw_rev); 87 if (get_current_fw_rev(&dev_fw_rev)) { 88 fprintf(stderr, "Couldn't query existing IFWI version\n"); 89 return -1; 90 } 91 fprintf(stderr, 92 "Attempting to flash ifwi image version %04X.%04X over ifwi current version %04X.%04X\n", 93 img_fw_rev.ifwi.major, img_fw_rev.ifwi.minor, dev_fw_rev.ifwi.major, dev_fw_rev.ifwi.minor); 94 95 if (img_fw_rev.ifwi.major != dev_fw_rev.ifwi.major) { 96 fprintf(stderr, 97 "IFWI FW Major version numbers (file=%04X current=%04X) don't match, Update abort.\n", 98 img_fw_rev.ifwi.major, dev_fw_rev.ifwi.major); 99 return -1; 100 } 101 102 return 1; 103 } 104 105 static uint32_t xor_compute(char *ptr, uint32_t size) 106 { 107 uint32_t val = 0; 108 uint32_t i; 109 110 for (i = 0; i < size; i+=4) 111 val = val ^ *(uint32_t *)(ptr + i); 112 113 return val; 114 } 115 116 static uint8_t xor_factorize(uint32_t val) 117 { 118 return (uint8_t)((val & 0xff) ^ ((val >> 8) & 0xff) ^ ((val >> 16) & 0xff) ^ ((val >> 24) & 0xff)); 119 } 120 121 static void xor_update(char *ptr) 122 { 123 uint16_t i; 124 uint32_t val; 125 126 /* update UMIP xor of sector 2 to 127 */ 127 for (i = 2; i < 128; i++) { 128 val = xor_compute(ptr + i * BOOT_UMIP_SECTOR_SIZE, BOOT_UMIP_SECTOR_SIZE); 129 *(uint32_t *)(ptr + 4 * i) = val; 130 } 131 132 /* update UMIP xor */ 133 *(ptr + BOOT_UMIP_XOR_OFFSET) = 0; 134 val= xor_compute(ptr, BOOT_UMIP_SIZE); 135 *(ptr + BOOT_UMIP_XOR_OFFSET) = xor_factorize(val); 136 137 /* update IFWI xor */ 138 *(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = 0x0; 139 val= xor_compute(ptr, BOOT_IFWI_SIZE); 140 *(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = val; 141 } 142 143 static int write_umip_emmc(uint32_t addr_offset, void *data, size_t size) 144 { 145 int boot_fd = 0; 146 int boot_index; 147 char boot_partition[FILE_PATH_SIZE]; 148 char boot_partition_force_ro[FILE_PATH_SIZE]; 149 char *ptr; 150 char *token_data; 151 152 if (addr_offset == IFWI_OFFSET) { 153 token_data = reinterpret_cast<char *>(malloc(TOKEN_UMIP_AREA_SIZE)); 154 if (!token_data) { 155 fprintf(stderr, "write_umip_emmc: Malloc error\n"); 156 return -1; 157 } 158 159 if (size > BOOT_IFWI_SIZE) { 160 fprintf(stderr, "write_umip_emmc: Truncating last %d bytes from the IFWI\n", 161 (size - BOOT_IFWI_SIZE)); 162 /* Since the last 144 bytes are the FUP header which are not required,*/ 163 /* we truncate it to fit into the boot partition. */ 164 size = BOOT_IFWI_SIZE; 165 } 166 } 167 168 for (boot_index = 0; boot_index < 2; boot_index++) { 169 snprintf(boot_partition, FILE_PATH_SIZE, "/dev/block/mmcblk0boot%d", boot_index); 170 snprintf(boot_partition_force_ro, FILE_PATH_SIZE, "/sys/block/mmcblk0boot%d/force_ro", boot_index); 171 172 if (force_rw(boot_partition_force_ro)) { 173 fprintf(stderr, "write_umip_emmc: unable to force_ro %s\n", boot_partition); 174 goto err_boot1; 175 } 176 boot_fd = open(boot_partition, O_RDWR); 177 if (boot_fd < 0) { 178 fprintf(stderr, "write_umip_emmc: failed to open %s\n", boot_partition); 179 goto err_boot1; 180 } 181 182 ptr = (char *)mmap(NULL, BOOT_IFWI_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0); 183 if (ptr == MAP_FAILED) { 184 fprintf(stderr, "write_umip_emmc: mmap failed on boot%d with error : %s\n", boot_index, strerror(errno)); 185 goto err_boot1; 186 } 187 188 if (addr_offset == IFWI_OFFSET) 189 memcpy(token_data, ptr + TOKEN_UMIP_AREA_OFFSET, TOKEN_UMIP_AREA_SIZE); 190 191 /* Write the data */ 192 if (addr_offset + size <= BOOT_IFWI_SIZE) 193 if (data == NULL) 194 memset(ptr + addr_offset, 0, size); 195 else 196 memcpy(ptr + addr_offset, data, size); 197 else { 198 fprintf(stderr, "write_umip_emmc: write failed\n"); 199 goto err_boot2; 200 } 201 202 if (addr_offset == IFWI_OFFSET) 203 memcpy(ptr + TOKEN_UMIP_AREA_OFFSET, token_data, TOKEN_UMIP_AREA_SIZE); 204 205 /* Compute and write xor */ 206 xor_update(ptr); 207 208 munmap(ptr, BOOT_IFWI_SIZE); 209 close(boot_fd); 210 } 211 212 if (addr_offset == IFWI_OFFSET) 213 free(token_data); 214 return 0; 215 216 err_boot2: 217 munmap(ptr, BOOT_IFWI_SIZE); 218 219 err_boot1: 220 if (addr_offset == IFWI_OFFSET) 221 free(token_data); 222 close(boot_fd); 223 return -1; 224 } 225 226 static int readbyte_umip_emmc(uint32_t addr_offset) 227 { 228 int boot_fd = 0; 229 char *ptr; 230 int value = 0; 231 232 if (force_rw("/sys/block/mmcblk0boot0/force_ro")) { 233 fprintf(stderr, "read_umip_emmc: unable to force_ro\n"); 234 goto err_boot1; 235 } 236 boot_fd = open("/dev/block/mmcblk0boot0", O_RDWR); 237 if (boot_fd < 0) { 238 fprintf(stderr, "read_umip_emmc: failed to open /dev/block/mmcblk0boot0\n"); 239 goto err_boot1; 240 } 241 242 ptr = (char *)mmap(NULL, BOOT_UMIP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0); 243 if (ptr == MAP_FAILED) { 244 fprintf(stderr, "read_umip_emmc: mmap failed on boot0 with error : %s\n", strerror(errno)); 245 goto err_boot1; 246 } 247 248 /* Read the data */ 249 if (addr_offset < BOOT_UMIP_SIZE) 250 value = (int)*(ptr + addr_offset); 251 else { 252 fprintf(stderr, "read_umip_emmc: read failed\n"); 253 goto err_boot2; 254 } 255 256 munmap(ptr, BOOT_UMIP_SIZE); 257 close(boot_fd); 258 259 return value; 260 261 err_boot2: 262 munmap(ptr, BOOT_UMIP_SIZE); 263 264 err_boot1: 265 close(boot_fd); 266 return -1; 267 } 268 269 int update_ifwi_file_scu_emmc(void *data, size_t size) 270 { 271 return write_umip_emmc(IFWI_OFFSET, data, size); 272 } 273 274 int flash_ifwi_scu_emmc(void *data, unsigned size) 275 { 276 int ret; 277 278 ret = check_ifwi_file_scu_emmc(data, size); 279 if (ret > 0) 280 return update_ifwi_file_scu_emmc(data, size); 281 282 return ret; 283 } 284 285 Value* FlashIfwiFuguFn(const char *name, State * state, int argc, Expr * argv[]) { 286 Value *ret = NULL; 287 char *filename = NULL; 288 unsigned char *buffer = NULL; 289 int ifwi_size; 290 FILE *f = NULL; 291 292 if (argc != 1) { 293 ErrorAbort(state, "%s() expected 1 arg, got %d", name, argc); 294 return NULL; 295 } 296 if (ReadArgs(state, argv, 1, &filename) < 0) { 297 ErrorAbort(state, "%s() invalid args ", name); 298 return NULL; 299 } 300 301 if (filename == NULL || strlen(filename) == 0) { 302 ErrorAbort(state, "filename argument to %s can't be empty", name); 303 goto done; 304 } 305 306 if ((f = fopen(filename,"rb")) == NULL) { 307 ErrorAbort(state, "Unable to open file %s: %s ", filename, strerror(errno)); 308 goto done; 309 } 310 311 fseek(f, 0, SEEK_END); 312 ifwi_size = ftell(f); 313 if (ifwi_size < 0) { 314 ErrorAbort(state, "Unable to get ifwi_size "); 315 goto done; 316 }; 317 fseek(f, 0, SEEK_SET); 318 319 if ((buffer = reinterpret_cast<unsigned char *>(malloc(ifwi_size))) == NULL) { 320 ErrorAbort(state, "Unable to alloc ifwi flash buffer of size %d", ifwi_size); 321 goto done; 322 } 323 fread(buffer, ifwi_size, 1, f); 324 fclose(f); 325 326 if(flash_ifwi_scu_emmc(buffer, ifwi_size) !=0) { 327 ErrorAbort(state, "Unable to flash ifwi in emmc"); 328 free(buffer); 329 goto done; 330 }; 331 332 free(buffer); 333 ret = StringValue(strdup("")); 334 335 done: 336 if (filename) 337 free(filename); 338 339 return ret; 340 } 341 342 void Register_librecovery_updater_fugu() { 343 RegisterFunction("fugu.flash_ifwi", FlashIfwiFuguFn); 344 } 345