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