/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "Utils.h" #include "BurnSdBoot.h" #include "mmc.h" #include "private_boot0.h" #include "private_toc.h" #define DEVNODE_PATH_SD "/dev/block/mmcblk0" #define SECTOR_SIZE 512 /*Normal boot 0 and boot 1 */ #define SD_BOOT0_SECTOR_START 16 #define SD_BOOT0_SIZE_KBYTES 32 #define SD_UBOOT_SECTOR_START_PRE 38192 #define SD_UBOOT_SECTOR_START 32800 #define SD_UBOOT_SIZE_KBYTES 1024 /*TOC0 : sector 16 - 256*/ #define SD_TOC0_SECTOR_START 16 #define SD_TOC0_SIZE_KBYTES 120 /*TOC1 : sector 32800 - 40960 */ #define SD_TOC1_SECTOR_START 32800 #define SD_TOC1_SIZE_KBYTES 4080 static int sd_boot0_start , sd_boot0_len; static int sd_boot1_start , sd_boot1_len; static int sd_boot1_start_pre , sd_boot1_len_pre; /*some chip (e.g. H8) BOOT0 save in mmcblk0boot0 */ #define SD_BOOT0_PERMISION "/sys/block/mmcblk0boot0/force_ro" #define DEVNODE_PATH_SD_BOOT0 "/dev/block/mmcblk0boot0" static void sdBootInit(void) { static int inited = 0; if (inited == 1) return ; if (check_soc_is_secure()) { //secure sd_boot0_start = SD_TOC0_SECTOR_START * SECTOR_SIZE; sd_boot0_len = SD_TOC0_SIZE_KBYTES * 1024; sd_boot1_start = SD_TOC1_SECTOR_START * SECTOR_SIZE ; sd_boot1_len = SD_TOC1_SIZE_KBYTES * 1024; } else { sd_boot0_start = SD_BOOT0_SECTOR_START * SECTOR_SIZE; sd_boot0_len = SD_BOOT0_SIZE_KBYTES * 1024; sd_boot1_start = SD_UBOOT_SECTOR_START * SECTOR_SIZE ; sd_boot1_len = SD_UBOOT_SIZE_KBYTES * 1024; } sd_boot1_start_pre = SD_UBOOT_SECTOR_START_PRE * SECTOR_SIZE ; sd_boot1_len_pre = SD_UBOOT_SIZE_KBYTES * 1024; inited =1; return; } static int writeSdBoot(int fd, void *buf, off_t offset, size_t bootsize) { if (lseek(fd, 0, SEEK_SET) == -1) { bb_debug("reset the cursor failed! the error num is %d:%s\n", errno, strerror(errno)); return -1; } if (lseek(fd, offset, SEEK_CUR) == -1) { bb_debug("lseek failed! the error num is %d:%s\n", errno, strerror(errno)); return -1; } bb_debug("Write sd boot : offset = 0x%lx, len= 0x%zx\n", offset, bootsize); int result = write(fd, buf, bootsize); fsync(fd); return result; } static int readSdBoot(int fd ,off_t offset, size_t bootsize, void *buffer) { memset(buffer, 0, bootsize); if (lseek(fd, 0, SEEK_SET) == -1) { bb_debug("reset the cursor failed! the error num is %d:%s\n", errno, strerror(errno)); return -1; } if (lseek(fd, offset, SEEK_CUR) == -1) { bb_debug("lseek failed! the error num is %d:%s\n", errno, strerror(errno)); return -1; } read(fd,buffer,bootsize); return 0; } static int updateBoot0Info(void *in_buffer, void *out_buffer,unsigned int buffer_size) { //struct boot_sdmmc_private_info_t priv_info; if ((in_buffer == NULL) ||(out_buffer == NULL) || (buffer_size < (sizeof(struct boot_sdmmc_private_info_t)))) { printf("%s %d:wrong input arg\n",__FUNCTION__,__LINE__); return -1; } /* ----- normal offset 0~127: boot0 struct _boot_sdcard_info_t; offset 128~255: struct tune_sdly, timing parameter for speed mode and frequency ----- secure offset 128 ~ (224=384-160): struct tune_sdly, timing parameter for speed mode and frequency sizeof(priv_info) is about 60 bytes. */ memcpy((void *)((unsigned char*)out_buffer+SDMMC_PRIV_INFO_ADDR_OFFSET), (void *)((unsigned char*)in_buffer + SDMMC_PRIV_INFO_ADDR_OFFSET), sizeof(struct boot_sdmmc_private_info_t)); { u32 i, *p; printf("out buffer\n"); p = (u32 *)((unsigned char*)out_buffer+SDMMC_PRIV_INFO_ADDR_OFFSET); for (i=0; i(malloc(cookie->len)); readSdBoot(fd, sd_boot0_start, cookie->len, buffer); if (check_soc_is_secure()) { sbrom_toc0_config_t *oldToc0Config = (sbrom_toc0_config_t *)(buffer + 0x80); sbrom_toc0_config_t *newToc0Config = (sbrom_toc0_config_t *)(cookie->buffer + 0x80); ret = updateBoot0Info((void *)(oldToc0Config->storage_data+160), (void *)(newToc0Config->storage_data+160), 384-160); } else { boot0_file_head_t *oldBoot0 = (boot0_file_head_t *)(buffer); boot0_file_head_t *newBoot0 = (boot0_file_head_t *)(cookie->buffer); ret = updateBoot0Info((void *)oldBoot0->prvt_head.storage_data, (void *)newBoot0->prvt_head.storage_data, STORAGE_BUFFER_SIZE); } if (ret == 0) genBoot0CheckSum(cookie->buffer); free(buffer); #endif return ret; } int burnSdBoot0(BufferExtractCookie *cookie) { sdBootInit(); if (checkBoot0Sum(cookie)){ bb_debug("illegal binary file!\n"); return -1; } int fd = open(DEVNODE_PATH_SD, O_RDWR); if (fd == -1) { bb_debug("open device node failed ! errno is %d : %s\n", errno, strerror(errno)); return -1; } bb_debug("burnSdBoot0 in mmcblk0:offset = 0x%x, len =0x%lx\n", sd_boot0_start, cookie->len); updateSdBoot0(fd, cookie); int ret = writeSdBoot(fd, cookie->buffer, sd_boot0_start, cookie->len); fsync(fd); close(fd); if (ret > 0) { bb_debug("burnSdBoot0 succeed! writed %d bytes\n", ret); } fd = open(DEVNODE_PATH_SD_BOOT0, O_RDWR); if (fd > 0) { int pmsFd = open(SD_BOOT0_PERMISION, O_WRONLY); if (pmsFd > 0) { ret = write(pmsFd,"0",1); close(pmsFd); } else { bb_debug("can't open %s :%s \n", SD_BOOT0_PERMISION, strerror(errno)); close(fd); return -1; } if (ret < 0) { bb_debug("can't write 0 to %s :%s \n", SD_BOOT0_PERMISION, strerror(errno)); close(fd); return -1; } // wipe boot0 in mmcblk0boot0 char *empty_buffer = (char *)malloc(cookie->len); memset(empty_buffer, 0, cookie->len); ret = writeSdBoot(fd, empty_buffer, 0, cookie->len); free(empty_buffer); if (ret > 0) { bb_debug("wipe boot0 in mmcblk0boot0 succeed! on %d writed %d bytes\n", 0, ret); } fsync(fd); } else { bb_debug("open device node failed ! errno is %d : %s\n", errno, strerror(errno)); } return ret; } int burnSdUboot(BufferExtractCookie *cookie) { sdBootInit(); char *empty_buffer; int ret = -1; int defaultOffset = -1; if (checkUbootSum(cookie) && checkBoot1Sum(cookie)) { bb_debug("illegal uboot binary file!\n"); return -1; } bb_debug("uboot binary length is %ld\n", cookie->len); int fd = open(DEVNODE_PATH_SD, O_RDWR); if (fd == -1) { bb_debug("open device node failed ! errno is %d : %s\n", errno, strerror(errno)); return -1; } if (check_soc_is_secure()) { ret = writeSdBoot(fd, cookie->buffer, sd_boot1_start, cookie->len); } else { empty_buffer = (char *)malloc(sd_boot1_len_pre); memset(empty_buffer, 0, sd_boot1_len_pre); writeSdBoot(fd, empty_buffer, sd_boot1_start_pre, sd_boot1_len_pre); free(empty_buffer); defaultOffset = getUbootstartsector(cookie) * SECTOR_SIZE; if (defaultOffset <= 0) defaultOffset = sd_boot1_start; ret = writeSdBoot(fd, cookie->buffer, defaultOffset, cookie->len); } close(fd); if (ret > 0) { bb_debug("burnSdUboot succeed! writed %d bytes\n", ret); } return ret; }