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