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;
112dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    unsigned base           = 0x10000000;
113dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    unsigned kernel_offset  = 0x00008000;
114dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    unsigned ramdisk_offset = 0x01000000;
115dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    unsigned second_offset  = 0x00f00000;
116dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    unsigned tags_offset    = 0x00000100;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argc--;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    argv++;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&hdr, 0, sizeof(hdr));
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(argc > 0){
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *arg = argv[0];
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *val = argv[1];
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(argc < 2) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return usage();
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        argc -= 2;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        argv += 2;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            bootimg = val;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--kernel")) {
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            kernel_fn = val;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--ramdisk")) {
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ramdisk_fn = val;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--second")) {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            second_fn = val;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--cmdline")) {
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmdline = val;
1412a63bb7abf1b27a7a2e8fd5951d77f71a2f290d4Brian Swetland        } else if(!strcmp(arg, "--base")) {
142dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker            base = strtoul(val, 0, 16);
143dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker        } else if(!strcmp(arg, "--kernel_offset")) {
144dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker            kernel_offset = strtoul(val, 0, 16);
145dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker        } else if(!strcmp(arg, "--ramdisk_offset")) {
146dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker            ramdisk_offset = strtoul(val, 0, 16);
147dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker        } else if(!strcmp(arg, "--second_offset")) {
148dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker            second_offset = strtoul(val, 0, 16);
149dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker        } else if(!strcmp(arg, "--tags_offset")) {
150dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker            tags_offset = strtoul(val, 0, 16);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if(!strcmp(arg, "--board")) {
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            board = val;
1538417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland        } else if(!strcmp(arg,"--pagesize")) {
1548417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            pagesize = strtoul(val, 0, 10);
1558417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            if ((pagesize != 2048) && (pagesize != 4096)) {
1568417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland                fprintf(stderr,"error: unsupported page size %d\n", pagesize);
1578417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland                return -1;
1588417d698cff733f3c5de08f2fa96b67bf4a9f795Brian Swetland            }
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return usage();
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
16365e461c478b000246ef81c3ca5fdd2dbb819d7adMaarten Hooft    hdr.page_size = pagesize;
16465e461c478b000246ef81c3ca5fdd2dbb819d7adMaarten Hooft
165dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    hdr.kernel_addr =  base + kernel_offset;
166dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    hdr.ramdisk_addr = base + ramdisk_offset;
167dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    hdr.second_addr =  base + second_offset;
168dd7fafb34bf86b8fb41043e568bf0dd1005a49ddDoug Zongker    hdr.tags_addr =    base + tags_offset;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(bootimg == 0) {
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no output filename specified\n");
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kernel_fn == 0) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no kernel image specified\n");
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ramdisk_fn == 0) {
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: no ramdisk image specified\n");
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(strlen(board) >= BOOT_NAME_SIZE) {
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: board name too large\n");
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return usage();
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy(hdr.name, board);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(hdr.magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(strlen(cmdline) > (BOOT_ARGS_SIZE - 1)) {
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: kernel commandline too large\n");
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    strcpy((char*)hdr.cmdline, cmdline);
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kernel_data = load_file(kernel_fn, &hdr.kernel_size);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(kernel_data == 0) {
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(ramdisk_fn,"NONE")) {
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ramdisk_data = 0;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        hdr.ramdisk_size = 0;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(ramdisk_data == 0) {
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(second_fn) {
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        second_data = load_file(second_fn, &hdr.second_size);
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(second_data == 0) {
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* put a hash of the contents in the header so boot images can be
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * differentiated based on their first 2k.
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     */
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_init(&ctx);
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, kernel_data, hdr.kernel_size);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.kernel_size, sizeof(hdr.kernel_size));
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, ramdisk_data, hdr.ramdisk_size);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.ramdisk_size, sizeof(hdr.ramdisk_size));
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, second_data, hdr.second_size);
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, &hdr.second_size, sizeof(hdr.second_size));
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sha = SHA_final(&ctx);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(hdr.id, sha,
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           SHA_DIGEST_SIZE > sizeof(hdr.id) ? sizeof(hdr.id) : SHA_DIGEST_SIZE);
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = open(bootimg, O_CREAT | O_TRUNC | O_WRONLY, 0644);
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(fd < 0) {
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"error: could not create '%s'\n", bootimg);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) goto fail;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, sizeof(hdr))) goto fail;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, kernel_data, hdr.kernel_size) != hdr.kernel_size) goto fail;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, hdr.kernel_size)) goto fail;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write(fd, ramdisk_data, hdr.ramdisk_size) != hdr.ramdisk_size) goto fail;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(second_data) {
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(write(fd, second_data, hdr.second_size) != hdr.second_size) goto fail;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(write_padding(fd, pagesize, hdr.ramdisk_size)) goto fail;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectfail:
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unlink(bootimg);
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close(fd);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr,"error: failed writing '%s': %s\n", bootimg,
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            strerror(errno));
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
268