2 * Copyright (C) 2014 Thadeu Lima de Souza Cascardo <cascardo@cascardo.eti.br>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 static int dump_or_load(int fd, size_t *len, int pgsz, char *fname, int dump)
40 cfd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0644);
42 cfd = open(fname, O_RDONLY);
58 npages = (*len + pgsz - 1) / pgsz;
59 for (i = 1; i <= npages; i++) {
61 rem = *len & (pgsz - 1);
63 r = read(ifd, page, rem);
66 r = write(ofd, page, rem);
71 memset(page, 0, pgsz - rem);
72 write(ofd, page, pgsz - rem);
76 r = read(ifd, page, pgsz);
79 r = write(ofd, page, pgsz);
95 static int dump(int fd, size_t len, int pgsz, char *fname)
97 return dump_or_load(fd, &len, pgsz, fname, 1);
100 static int load(int fd, size_t *len, int pgsz, char *fname)
102 return dump_or_load(fd, len, pgsz, fname, 0);
105 int main(int argc, char **argv)
108 uint32_t *kernel, *initrd, *second, pgsz;
119 fd = open(argv[1], O_RDWR);
121 fd = open(argv[1], O_RDONLY);
125 r = read(fd, buffer, sizeof(buffer));
129 if (strncmp(buffer, "ANDROID!", 8)) {
132 kernel = (uint32_t *) p;
134 initrd = (uint32_t *) p;
136 second = (uint32_t *) p;
138 pgsz = *(uint32_t *) p;
140 if (!is_load && *kernel > 0) {
141 lseek(fd, offset, SEEK_SET);
142 dump(fd, *kernel, pgsz, "kernel");
144 lseek(fd, offset, SEEK_SET);
145 load(fd, kernel, pgsz, "kernel");
147 offset += ((*kernel + pgsz - 1) / pgsz) * pgsz;
148 if (!is_load && *initrd > 0) {
149 lseek(fd, offset, SEEK_SET);
150 dump(fd, *initrd, pgsz, "initrd");
152 lseek(fd, offset, SEEK_SET);
153 load(fd, initrd, pgsz, "initrd");
155 offset += ((*initrd + pgsz - 1) / pgsz) * pgsz;
156 if (!is_load && *second > 0) {
157 lseek(fd, offset, SEEK_SET);
158 dump(fd, *second, pgsz, "second");
160 /* For now, don't care about using second. */
161 /* The header must be written back, and we may need to
162 * truncate the file. */
163 ftruncate(fd, offset);
164 lseek(fd, 0, SEEK_SET);
165 write(fd, buffer, pgsz);