mkbootimg.c revision fc2f7cb69e3f15a616330a69f0675675c68112f3
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* tools/mkbootimg/mkbootimg.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2007, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mincrypt/sha.h"
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "bootimg.h"
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *load_file(const char *fn, unsigned *_sz)
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *data;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int sz;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = 0;
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(fn, O_RDONLY);
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) return 0;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sz = lseek(fd, 0, SEEK_END);
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(sz < 0) goto oops;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = (char*) malloc(sz);
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data == 0) goto oops;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(read(fd, data, sz) != sz) goto oops;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(_sz) *_sz = sz;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return data;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectoops:
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(data != 0) free(data);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usage(void)
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"usage: mkbootimg\n"
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       --kernel <filename>\n"
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       --ramdisk <filename>\n"
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       [ --second <2ndbootloader-filename> ]\n"
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       [ --cmdline <kernel-commandline> ]\n"
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       [ --board <boardname> ]\n"
662a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            "       [ --base <address> ]\n"
67fc2f7cb69e3f15a616330a69f0675675c68112f3Ying Wang            "       [ --pagesize <pagesize> ]\n"
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "       -o|--output <filename>\n"
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            );
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
758417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetlandstatic unsigned char padding[4096] = { 0, };
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint write_padding(int fd, unsigned pagesize, unsigned itemsize)
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned pagemask = pagesize - 1;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((itemsize & pagemask) == 0) {
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = pagesize - (itemsize & pagemask);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, padding, count) != count) {
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint main(int argc, char **argv)
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    boot_img_hdr hdr;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *kernel_fn = 0;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *kernel_data = 0;
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *ramdisk_fn = 0;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *ramdisk_data = 0;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *second_fn = 0;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *second_data = 0;
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *cmdline = "";
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *bootimg = 0;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *board = "";
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned pagesize = 2048;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_CTX ctx;
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t* sha;
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argc--;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argv++;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&hdr, 0, sizeof(hdr));
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1182a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland        /* default load addresses */
1192a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    hdr.kernel_addr =  0x10008000;
1202a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    hdr.ramdisk_addr = 0x11000000;
1212a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    hdr.second_addr =  0x10F00000;
1222a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    hdr.tags_addr =    0x10000100;
1232a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
1242a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland    hdr.page_size = pagesize;
1252a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(argc > 0){
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *arg = argv[0];
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *val = argv[1];
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(argc < 2) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return usage();
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        argc -= 2;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        argv += 2;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            bootimg = val;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--kernel")) {
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            kernel_fn = val;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--ramdisk")) {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ramdisk_fn = val;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--second")) {
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            second_fn = val;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--cmdline")) {
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmdline = val;
1442a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland        } else if(!strcmp(arg, "--base")) {
1452a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            unsigned base = strtoul(val, 0, 16);
1462a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            hdr.kernel_addr =  base + 0x00008000;
1472a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            hdr.ramdisk_addr = base + 0x01000000;
1482a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            hdr.second_addr =  base + 0x00F00000;
1492a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland            hdr.tags_addr =    base + 0x00000100;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--board")) {
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            board = val;
1528417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland        } else if(!strcmp(arg,"--pagesize")) {
1538417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            pagesize = strtoul(val, 0, 10);
1548417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            if ((pagesize != 2048) && (pagesize != 4096)) {
1558417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland                fprintf(stderr,"error: unsupported page size %d\n", pagesize);
1568417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland                return -1;
1578417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            }
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return usage();
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(bootimg == 0) {
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no output filename specified\n");
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kernel_fn == 0) {
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no kernel image specified\n");
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ramdisk_fn == 0) {
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no ramdisk image specified\n");
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(strlen(board) >= BOOT_NAME_SIZE) {
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: board name too large\n");
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(hdr.name, board);
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: kernel commandline too large\n");
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy((char*)hdr.cmdline, cmdline);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kernel_data = load_file(kernel_fn, &hdr.kernel_size);
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kernel_data == 0) {
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(ramdisk_fn,"NONE")) {
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ramdisk_data = 0;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        hdr.ramdisk_size = 0;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ramdisk_data == 0) {
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(second_fn) {
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        second_data = load_file(second_fn, &hdr.second_size);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(second_data == 0) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* put a hash of the contents in the header so boot images can be
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * differentiated based on their first 2k.
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     */
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_init(&ctx);
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, kernel_data, hdr.kernel_size);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, second_data, hdr.second_size);
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sha = SHA_final(&ctx);
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(hdr.id, sha,
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: could not create '%s'\n", bootimg);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(second_data) {
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unlink(bootimg);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strerror(errno));
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
261