allwinner_a64/android/device/softwinner/common/recovery/BurnSdBoot.cpp
2018-08-08 17:48:24 +08:00

254 lines
8.5 KiB
C++
Executable file

/*
* 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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#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<sizeof(struct boot_sdmmc_private_info_t)/4; i++)
printf("%d %x\n", i, p[i]);
}
{
u32 i, *p;
printf("int buffer\n");
p = (u32 *)((unsigned char*)in_buffer+SDMMC_PRIV_INFO_ADDR_OFFSET);
for (i=0; i<sizeof(struct boot_sdmmc_private_info_t)/4; i++)
printf("%d %x\n", i, p[i]);
}
return 0;
}
static int updateSdBoot0(int fd, BufferExtractCookie *cookie) {
int ret = 0;
#if RESTORE_BOOT_STORAGE_DATA
unsigned char* buffer = reinterpret_cast<unsigned char *>(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;
}