1bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross/* 2bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * Copyright (C) 2011 The Android Open Source Project 3bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * 4bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 5bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * you may not use this file except in compliance with the License. 6bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * You may obtain a copy of the License at 7bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * 8bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * http://www.apache.org/licenses/LICENSE-2.0 9bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * 10bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * Unless required by applicable law or agreed to in writing, software 11bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * distributed under the License is distributed on an "AS IS" BASIS, 12bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * See the License for the specific language governing permissions and 14bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross * limitations under the License. 15bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross */ 16bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 17bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <errno.h> 18bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <fcntl.h> 19bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <stdio.h> 20bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <stdlib.h> 21bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <unistd.h> 22bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 23bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <sys/mount.h> 24bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <sys/types.h> 25bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <sys/reboot.h> 26bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#include <sys/stat.h> 27bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 28bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define error(s, a...) \ 29bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross { \ 30bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("error: " s "\n", ##a); \ 31bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross exit(-1); \ 32bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 33bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 34bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define error_errno(s, a...) error(s ": %s", ##a, strerror(errno)) 35bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 36bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) 37bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 38bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossenum omap_type_enum { 39bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross OMAP4460_EMU = 0, 40bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross OMAP4460_HS, 41bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross OMAP4460_HS_PROD, 42bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross OMAP4430_HS, 43bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross}; 44bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 45bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstruct omap_type { 46bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross const char *family; 47bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross const char *type; 48bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross unsigned long msv_val; 49bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross const char *msv_type; 50bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross off_t offset; 51bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} omap_type_list[] = { 52bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross [OMAP4460_EMU] = {"OMAP4460", "EMU", 0x00000000, "eng", 0x1000}, 53bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross [OMAP4460_HS] = {"OMAP4460", "HS", 0x00000000, "eng", 0x21000}, 54bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross [OMAP4460_HS_PROD] = {"OMAP4460", "HS", 0xf0000f00, "prod", 0x41000}, 55bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross [OMAP4430_HS] = {"OMAP4430", "HS", 0x00000000, "eng", 0x61000}, 56bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross}; 57bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 58bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define IMG_PIT_OFFSET 0UL 59bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define IMG_SBL_OFFSET 0x81000UL 60bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 61bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define MMC_PIT_OFFSET 0x4400UL 62bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define MMC_XLOADER_OFFSET 0x20000UL 63bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define MMC_SBL_OFFSET 0x80000UL 64bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 65bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define PIT_SIZE 0x1000UL 66bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#define XLOADER_SIZE 0x20000UL 67bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 68bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void drop_caches(void) 69bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 70bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int fd; 71bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int ret; 72bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char buf[] = "3\n"; 73bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 74bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross fd = open("/proc/sys/vm/drop_caches", O_WRONLY); 75bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (fd < 0) 76bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to open /proc/sys/vm/drop_caches"); 77bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 78bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = write(fd, buf, sizeof(buf)); 79bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 80bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to write to /proc/sys/vm/drop_caches"); 81bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 82bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 83bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void read_file(const char *filename, char *buf, size_t size) 84bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 85bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int fd; 86bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ssize_t ret; 87bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 88bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross fd = open(filename, O_RDONLY); 89bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (fd < 0) 90bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to open %s", filename); 91bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 92bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = read(fd, buf, size - 1); 93bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 94bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to read %s", filename); 95bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross buf[ret] = 0; 96bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (buf[ret - 1] == '\n') 97bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross buf[--ret] = 0; 98bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 99bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross close(fd); 100bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 101bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 102bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic const struct omap_type *get_omap_type(void) 103bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 104bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int fd; 105bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char family[10]; 106bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char type[5]; 107bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char msv[9]; 108bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross unsigned long msv_val; 109bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ssize_t ret; 110bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross unsigned int i; 111bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 112bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross read_file("/sys/board_properties/soc/type", type, sizeof(type)); 113bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross read_file("/sys/board_properties/soc/family", family, sizeof(family)); 114bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross read_file("/sys/board_properties/soc/msv", msv, sizeof(msv)); 115bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 116bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross msv_val = strtoul(msv, NULL, 16); 117bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 118bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross for (i = 0; i < ARRAY_SIZE(omap_type_list); i++) 119bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if ((strcmp(omap_type_list[i].family, family) == 0) && 120bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross (strcmp(omap_type_list[i].type, type) == 0) && 121bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross msv_val == omap_type_list[i].msv_val) 122bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross return &omap_type_list[i]; 123bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 124bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error("unknown omap type %s %s %s (0x%08lx)", family, type, msv, msv_val); 125bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 126bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 127bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void zero_data(int to_fd, off_t to_offset, ssize_t size) 128bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 129bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char buf[4096]; 130bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int ret; 131bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross unsigned int to_write; 132bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 133bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross memset(buf, 0, sizeof(buf)); 134bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 135bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = lseek(to_fd, to_offset, SEEK_SET); 136bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 137bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to seek output file to %lx", to_offset); 138bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 139bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (size != 0) { 140bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_write = size; 141bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (to_write > sizeof(buf)) 142bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_write = sizeof(buf); 143bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 144bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = write(to_fd, buf, to_write); 145bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 146bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to write to output file"); 147bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross size -= ret; 148bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 149bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 150bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 151bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void verify_data(int to_fd, off_t to_offset, 152bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int from_fd, off_t from_offset, 153bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ssize_t size) 154bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 155bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char buf_to[4096]; 156bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char buf_from[4096]; 157bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int ret; 158bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int to_read; 159bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int c; 160bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char *ptr; 161bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 162bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = lseek(to_fd, to_offset, SEEK_SET); 163bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 164bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to seek output file to %lx", to_offset); 165bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 166bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = lseek(from_fd, from_offset, SEEK_SET); 167bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 168bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to seek input file to %lx", from_offset); 169bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 170bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (size != 0) { 171bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_read = sizeof(buf_to); 172bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (size > 0 && to_read > size) 173bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_read = size; 174bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 175bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr = buf_to; 176bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross c = to_read; 177bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (c > 0) { 178bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = read(to_fd, ptr, c); 179bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 180bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to read from output file"); 181bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0 && size < 0) 182bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross return; 183bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0) 184bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("eof while reading output file"); 185bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr += ret; 186bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross c -= ret; 187bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 188bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 189bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr = buf_from; 190bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross c = to_read; 191bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (c > 0) { 192bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = read(from_fd, ptr, c); 193bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 194bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to read from input file"); 195bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0 && size < 0) 196bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross return; 197bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0) 198bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("eof while reading input file"); 199bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr += ret; 200bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross c -= ret; 201bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 202bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 203bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (memcmp(buf_from, buf_to, to_read) != 0) 204bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error("mismatch while verifying written data"); 205bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 206bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross size -= to_read; 207bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 208bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 209bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 210bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void copy_data(int to_fd, off_t to_offset, 211bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int from_fd, off_t from_offset, 212bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ssize_t size) 213bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 214bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross char buf[4096]; 215bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int ret; 216bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int to_write; 217bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross const char *ptr; 218bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 219bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = lseek(to_fd, to_offset, SEEK_SET); 220bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 221bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to seek output file to %lx", to_offset); 222bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 223bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = lseek(from_fd, from_offset, SEEK_SET); 224bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 225bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to seek input file to %lx", from_offset); 226bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 227bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (size != 0) { 228bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = read(from_fd, buf, sizeof(buf)); 229bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 230bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to read from input file"); 231bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0 && size > 0) 232bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("eof while reading input file"); 233bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret == 0) 234bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross return; 235bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 236bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_write = ret; 237bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr = buf; 238bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 239bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (size > 0) 240bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross size -= to_write; 241bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 242bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (to_write > 0) { 243bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = write(to_fd, ptr, to_write); 244bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret < 0) 245bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to write to output file"); 246bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross to_write -= ret; 247bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ptr += ret; 248bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 249bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 250bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 251bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 252bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossstatic void init(void) 253bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 254bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int ret; 255bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 256bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross umask(0); 257bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 258bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mkdir("/dev", 0755); 259bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret && errno != EEXIST) 260bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to create /dev"); 261bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 262bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mkdir("/proc", 0755); 263bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret && errno != EEXIST) 264bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to create /proc"); 265bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 266bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mkdir("/sys", 0755); 267bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret && errno != EEXIST) 268bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to create /sys"); 269bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 270bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mount("proc", "/proc", "proc", 0, NULL); 271bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret) 272bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to mount proc"); 273bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 274bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mount("sysfs", "/sys", "sysfs", 0, NULL); 275bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret) 276bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to mount sys"); 277bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 278bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mkdir("/dev/block", 0755); 279bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret && errno != EEXIST) 280bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to create /dev/block"); 281bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 282bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross ret = mknod("/dev/block/mmcblk0", S_IFBLK | 0755, makedev(179, 0)); 283bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (ret) 284bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to create mmcblk0"); 285bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 286bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 287bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Crossint main(int argc, char **argv) 288bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross{ 289bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int in_fd; 290bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross int out_fd; 291bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross const struct omap_type *type; 292bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 293bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (getpid() == 1) 294bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross init(); 295bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 296bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross in_fd = open("bootloader.img", O_RDONLY); 297bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (in_fd < 0) 298bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to open bootloader.img"); 299bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 300bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross out_fd = open("/dev/block/mmcblk0", O_RDWR); 301bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (out_fd < 0) 302bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross error_errno("failed to open mmcblk0"); 303bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 304bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross type = get_omap_type(); 305bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 306bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Found %s %s %s\n", type->family, type->type, type->msv_type); 307bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 308bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Zeroing to end of sbl\n"); 309bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross zero_data(out_fd, 0, MMC_SBL_OFFSET); 310bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 311bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross /* Don't write the partition table, let the bootloader do it on next boot */ 312bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#if 0 313bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Writing partition-table from %lx to %lx\n", 314bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross IMG_PIT_OFFSET, MMC_PIT_OFFSET); 315bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross copy_data(out_fd, MMC_PIT_OFFSET, in_fd, IMG_PIT_OFFSET, PIT_SIZE); 316bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#endif 317bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 318bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Writing xloader from %lx to %lx\n", 319bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross type->offset, MMC_XLOADER_OFFSET); 320bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross copy_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE); 321bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 322bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Writing sbl from %lx to %lx\n", 323bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross IMG_SBL_OFFSET, MMC_SBL_OFFSET); 324bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross copy_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1); 325bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 326bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#if 0 327bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Verifying partition table\n"); 328bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross verify_data(out_fd, MMC_PIT_OFFSET, in_fd, IMG_PIT_OFFSET, PIT_SIZE); 329bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross#endif 330bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 331bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Verifying xloader\n"); 332bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross verify_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE); 333bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 334bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Verifying sbl\n"); 335bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross verify_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1); 336bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 337bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Syncing\n"); 338bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross sync(); 339bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 340bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Dropping caches\n"); 341bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross drop_caches(); 342bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 343bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Verifying xloader.img\n"); 344bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross verify_data(out_fd, MMC_XLOADER_OFFSET, in_fd, type->offset, XLOADER_SIZE); 345bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 346bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Verifying sbl.img\n"); 347bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross verify_data(out_fd, MMC_SBL_OFFSET, in_fd, IMG_SBL_OFFSET, -1); 348bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 349bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross printf("Done\n"); 350bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 351bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross if (getpid() == 1) { 352bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 353bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross LINUX_REBOOT_CMD_RESTART2, "bootloader"); 354bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 355bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross while (1) { sleep(1); } 356bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross } 357bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross 358bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross return 0; 359bff25f157e2e6a9fde1691e2173245c7e2b0c3c3Colin Cross} 360