189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos/*
289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * Copyright 2014 Intel Corporation
389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos *
489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * Licensed under the Apache License, Version 2.0 (the "License");
589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * you may not use this file except in compliance with the License.
689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * You may obtain a copy of the License at
789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos *
889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos *     http://www.apache.org/licenses/LICENSE-2.0
989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos *
1089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * Unless required by applicable law or agreed to in writing, software
1189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * distributed under the License is distributed on an "AS IS" BASIS,
1289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * See the License for the specific language governing permissions and
1489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos * limitations under the License.
1589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos */
1689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
17ee118cf15b62f076ae262fea80f77c32fa3695d6Elliott Hughes#include <errno.h>
1889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <stdio.h>
1989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <unistd.h>
2089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <stdbool.h>
21deaaf79a745176e24a12b55cbf0f5e74948e10dfElliott Hughes#include <stdlib.h>
22deaaf79a745176e24a12b55cbf0f5e74948e10dfElliott Hughes#include <string.h>
2389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <sys/types.h>
2489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <sys/stat.h>
2589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <fcntl.h>
2689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <cutils/properties.h>
2789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include <sys/mman.h>
287a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu
2926d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie Xu#include <memory>
307a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu#include <string>
317a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu#include <vector>
327a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu
3389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include "fw_version_check.h"
3489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#include "edify/expr.h"
3589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
3689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define FORCE_RW_OPT            "0"
3789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_IFWI_SIZE          0x400000
3889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_UMIP_SIZE          0x10000
3989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_UMIP_SECTOR_SIZE   0x200
4089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_UMIP_XOR_OFFSET    0x7
4189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_UMIP_3GPP_OFFSET   0x76F
4289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_IFWI_XOR_OFFSET    0x0112d8
4389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define BOOT_DNX_TIMEOUT_OFFSET 0x400
4489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define IFWI_OFFSET             0
4589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define TOKEN_UMIP_AREA_OFFSET  0x4000
4689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define TOKEN_UMIP_AREA_SIZE    0x2C00
4789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define FILE_PATH_SIZE          64
4889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos#define IFWI_TYPE_LSH           12
4989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
5089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosstatic void dump_fw_versions(struct firmware_versions *v)
5189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
5289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "Image FW versions:\n");
5389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "	   ifwi: %04X.%04X\n", v->ifwi.major, v->ifwi.minor);
5489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "---- components ----\n");
5589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "	    scu: %04X.%04X\n", v->scu.major, v->scu.minor);
5689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "    hooks/oem: %04X.%04X\n", v->valhooks.major, v->valhooks.minor);
5789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "	   ia32: %04X.%04X\n", v->ia32.major, v->ia32.minor);
5889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "	 chaabi: %04X.%04X\n", v->chaabi.major, v->chaabi.minor);
5989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr, "	    mIA: %04X.%04X\n", v->mia.major, v->mia.minor);
6089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
6189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
623ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Baostatic int force_rw(const char *name) {
6389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int ret, fd;
6489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
6589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fd = open(name, O_WRONLY);
6689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (fd < 0) {
6789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "force_ro(): failed to open %s\n", name);
6889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return fd;
6989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
7089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
7189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	ret = write(fd, FORCE_RW_OPT, sizeof(FORCE_RW_OPT));
7289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (ret <= 0) {
7389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "force_ro(): failed to write %s\n", name);
7489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		close(fd);
7589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return ret;
7689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
7789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
7889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	close(fd);
7989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return 0;
8089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
8189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
8289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosint check_ifwi_file_scu_emmc(void *data, size_t size)
8389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
8489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	struct firmware_versions dev_fw_rev, img_fw_rev;
8589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
8689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (get_image_fw_rev(data, size, &img_fw_rev)) {
8789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "Coudn't extract FW version data from image\n");
8889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return -1;
8989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
9089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
9189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	dump_fw_versions(&img_fw_rev);
9289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (get_current_fw_rev(&dev_fw_rev)) {
9389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "Couldn't query existing IFWI version\n");
9489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return -1;
9589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
9689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fprintf(stderr,
9789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		"Attempting to flash ifwi image version %04X.%04X over ifwi current version %04X.%04X\n",
9889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		img_fw_rev.ifwi.major, img_fw_rev.ifwi.minor, dev_fw_rev.ifwi.major, dev_fw_rev.ifwi.minor);
9989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
10089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (img_fw_rev.ifwi.major != dev_fw_rev.ifwi.major) {
10189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr,
10289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			"IFWI FW Major version numbers (file=%04X current=%04X) don't match, Update abort.\n",
10389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			img_fw_rev.ifwi.major, dev_fw_rev.ifwi.major);
104838d53c304ff966d4170776681d2ac733940ecbcSylvain Chouleur		return -1;
10589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
10689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
10789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return 1;
10889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
10989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
11089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosstatic uint32_t xor_compute(char *ptr, uint32_t size)
11189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
1123ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	uint32_t val = 0;
11389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	uint32_t i;
11489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
11589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	for (i = 0; i < size; i+=4)
1163ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao		val = val ^ *(uint32_t *)(ptr + i);
11789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
1183ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	return val;
11989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
12089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
1213ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Baostatic uint8_t xor_factorize(uint32_t val)
12289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
1233ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	return (uint8_t)((val & 0xff) ^ ((val >> 8) & 0xff) ^ ((val >> 16) & 0xff) ^ ((val >> 24) & 0xff));
12489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
12589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
12689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosstatic void xor_update(char *ptr)
12789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
12889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	uint16_t i;
1293ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	uint32_t val;
13089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
13189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	/* update UMIP xor of sector 2 to 127 */
13289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	for (i = 2; i < 128; i++) {
1333ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao		val = xor_compute(ptr + i * BOOT_UMIP_SECTOR_SIZE, BOOT_UMIP_SECTOR_SIZE);
1343ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao		*(uint32_t *)(ptr + 4 * i) = val;
13589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
13689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
13789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	/* update UMIP xor */
13889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	*(ptr + BOOT_UMIP_XOR_OFFSET) = 0;
1393ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	val= xor_compute(ptr, BOOT_UMIP_SIZE);
1403ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	*(ptr + BOOT_UMIP_XOR_OFFSET) = xor_factorize(val);
14189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
14289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	/* update IFWI xor */
14389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	*(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = 0x0;
1443ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	val= xor_compute(ptr, BOOT_IFWI_SIZE);
1453ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	*(uint32_t *)(ptr + BOOT_IFWI_XOR_OFFSET) = val;
14689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
14789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
14889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosstatic int write_umip_emmc(uint32_t addr_offset, void *data, size_t size)
14989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
15089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int boot_fd = 0;
15189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int boot_index;
15289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	char boot_partition[FILE_PATH_SIZE];
15389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	char boot_partition_force_ro[FILE_PATH_SIZE];
15489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	char *ptr;
15589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	char *token_data;
15689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
15789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (addr_offset == IFWI_OFFSET) {
1583ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao		token_data = reinterpret_cast<char *>(malloc(TOKEN_UMIP_AREA_SIZE));
15989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (!token_data) {
16089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: Malloc error\n");
16189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			return -1;
16289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
16389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
16489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (size > BOOT_IFWI_SIZE) {
16589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: Truncating last %d bytes from the IFWI\n",
16689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			(size - BOOT_IFWI_SIZE));
16789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			/* Since the last 144 bytes are the FUP header which are not required,*/
16889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			/* we truncate it to fit into the boot partition. */
16989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			size = BOOT_IFWI_SIZE;
17089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
17189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
17289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
17389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	for (boot_index = 0; boot_index < 2; boot_index++) {
17489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		snprintf(boot_partition, FILE_PATH_SIZE, "/dev/block/mmcblk0boot%d", boot_index);
17589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		snprintf(boot_partition_force_ro, FILE_PATH_SIZE, "/sys/block/mmcblk0boot%d/force_ro", boot_index);
17689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
17789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (force_rw(boot_partition_force_ro)) {
17889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: unable to force_ro %s\n", boot_partition);
17989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			goto err_boot1;
18089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
18189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		boot_fd = open(boot_partition, O_RDWR);
18289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (boot_fd < 0) {
18389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: failed to open %s\n", boot_partition);
18489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			goto err_boot1;
18589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
18689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
18789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		ptr = (char *)mmap(NULL, BOOT_IFWI_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0);
18889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (ptr == MAP_FAILED) {
18989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: mmap failed on boot%d with error : %s\n", boot_index, strerror(errno));
19089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			goto err_boot1;
19189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
19289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
19389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (addr_offset == IFWI_OFFSET)
19489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			memcpy(token_data, ptr + TOKEN_UMIP_AREA_OFFSET, TOKEN_UMIP_AREA_SIZE);
19589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
19689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		/* Write the data */
19789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (addr_offset + size <= BOOT_IFWI_SIZE)
19889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			if (data == NULL)
19989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos				memset(ptr + addr_offset, 0, size);
20089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			else
20189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos				memcpy(ptr + addr_offset, data, size);
20289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		else {
20389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			fprintf(stderr, "write_umip_emmc: write failed\n");
20489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			goto err_boot2;
20589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		}
20689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
20789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		if (addr_offset == IFWI_OFFSET)
20889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos			memcpy(ptr + TOKEN_UMIP_AREA_OFFSET, token_data, TOKEN_UMIP_AREA_SIZE);
20989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
21089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		/* Compute and write xor */
21189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		xor_update(ptr);
21289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
21389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		munmap(ptr, BOOT_IFWI_SIZE);
21489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		close(boot_fd);
21589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
21689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
21789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (addr_offset == IFWI_OFFSET)
21889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		free(token_data);
21989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return 0;
22089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
22189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenoserr_boot2:
22289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	munmap(ptr, BOOT_IFWI_SIZE);
22389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
22489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenoserr_boot1:
22589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (addr_offset == IFWI_OFFSET)
22689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		free(token_data);
22789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	close(boot_fd);
22889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return -1;
22989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
23089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
23189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosstatic int readbyte_umip_emmc(uint32_t addr_offset)
23289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
23389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int boot_fd = 0;
23489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	char *ptr;
23589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int value = 0;
23689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
23789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (force_rw("/sys/block/mmcblk0boot0/force_ro")) {
23889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "read_umip_emmc: unable to force_ro\n");
23989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		goto err_boot1;
24089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
24189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	boot_fd = open("/dev/block/mmcblk0boot0", O_RDWR);
24289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (boot_fd < 0) {
24389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "read_umip_emmc: failed to open /dev/block/mmcblk0boot0\n");
24489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		goto err_boot1;
24589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
24689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
24789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	ptr = (char *)mmap(NULL, BOOT_UMIP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, boot_fd, 0);
24889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (ptr == MAP_FAILED) {
24989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "read_umip_emmc: mmap failed on boot0 with error : %s\n", strerror(errno));
25089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		goto err_boot1;
25189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
25289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
25389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	/* Read the data */
25489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (addr_offset < BOOT_UMIP_SIZE)
25589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		value = (int)*(ptr + addr_offset);
25689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	else {
25789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		fprintf(stderr, "read_umip_emmc: read failed\n");
25889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		goto err_boot2;
25989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
26089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
26189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	munmap(ptr, BOOT_UMIP_SIZE);
26289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	close(boot_fd);
26389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
26489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return value;
26589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
26689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenoserr_boot2:
26789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	munmap(ptr, BOOT_UMIP_SIZE);
26889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
26989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenoserr_boot1:
27089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	close(boot_fd);
27189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return -1;
27289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
27389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
27489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosint update_ifwi_file_scu_emmc(void *data, size_t size)
27589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
27689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return write_umip_emmc(IFWI_OFFSET, data, size);
27789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
27889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
27989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosint flash_ifwi_scu_emmc(void *data, unsigned size)
28089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos{
28189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int ret;
28289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
28389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	ret = check_ifwi_file_scu_emmc(data, size);
28489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (ret > 0)
28589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return update_ifwi_file_scu_emmc(data, size);
28689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
28789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return ret;
28889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
28989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
29026d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie XuValue* FlashIfwiFuguFn(const char *name, State * state,
29126d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie Xu                       const std::vector<std::unique_ptr<Expr>>& argv) {
29289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	Value *ret = NULL;
29389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	unsigned char *buffer = NULL;
29489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	int ifwi_size;
29589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	FILE *f = NULL;
29689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
29726d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie Xu	if (argv.size() != 1) {
29826d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie Xu		ErrorAbort(state, "%s() expected 1 arg, got %zu", name, argv.size());
29989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return NULL;
30089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
3017a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu	std::vector<std::string> args;
30226d1d7701cc2945c29f0d8a1ee6e33c4b5d70130Tianjie Xu	if (!ReadArgs(state, argv, &args)) {
30389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		ErrorAbort(state, "%s() invalid args ", name);
30489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		return NULL;
30589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
3067a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu	const std::string& filename = args[0];
3077a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu	if (filename.empty()) {
30889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		ErrorAbort(state, "filename argument to %s can't be empty", name);
3097a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		return nullptr;
31089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
31189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
3127a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu	if ((f = fopen(filename.c_str(),"rb")) == NULL) {
3137a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		ErrorAbort(state, "Unable to open file %s: %s ", filename.c_str(), strerror(errno));
3147a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		return nullptr;
31589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	}
31689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
31789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fseek(f, 0, SEEK_END);
31889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	ifwi_size = ftell(f);
31989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if (ifwi_size < 0) {
32089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		ErrorAbort(state, "Unable to get ifwi_size ");
3217a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		return nullptr;
32289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	};
32389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fseek(f, 0, SEEK_SET);
32489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
3253ed0cf2c1acc8ab7b94b720fe2b414ec445e142cTao Bao	if ((buffer = reinterpret_cast<unsigned char *>(malloc(ifwi_size))) == NULL) {
3269223a5b545f10b5b494790295a0b940e0c8335a6Benoit Fradin		ErrorAbort(state, "Unable to alloc ifwi flash buffer of size %d", ifwi_size);
3277a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		return nullptr;
3289223a5b545f10b5b494790295a0b940e0c8335a6Benoit Fradin	}
32989c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fread(buffer, ifwi_size, 1, f);
33089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	fclose(f);
33189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
33289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	if(flash_ifwi_scu_emmc(buffer, ifwi_size) !=0) {
33389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		ErrorAbort(state, "Unable to flash ifwi in emmc");
33489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos		free(buffer);
3357a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu		return nullptr;
33689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	};
33789c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
33889c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	free(buffer);
3397a16fb337b8ecfe31e1b1a28616059952f49b49dTianjie Xu	ret = StringValue("");
34089c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
34189c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	return ret;
34289c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
34389c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos
34489c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenosvoid Register_librecovery_updater_fugu() {
34589c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos	RegisterFunction("fugu.flash_ifwi", FlashIfwiFuguFn);
34689c83d1a6f8a95121f28c3f6c10ef9208aa5923emarie cecile afantenos}
347