md: Protect access to mddev->disks list using RCU
[pandora-kernel.git] / arch / ppc / boot / utils / mkbugboot.c
1 /*
2  * Makes a Motorola PPCBUG ROM bootable image which can be flashed
3  * into one of the FLASH banks on a Motorola PowerPlus board.
4  *
5  * Author: Matt Porter <mporter@mvista.com>
6  *
7  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
8  * the terms of the GNU General Public License version 2.  This program
9  * is licensed "as is" without any warranty of any kind, whether express
10  * or implied.
11  */
12
13 #define ELF_HEADER_SIZE 65536
14
15 #include <unistd.h>
16 #include <sys/stat.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <netinet/in.h>
23 #ifdef __sun__
24 #include <inttypes.h>
25 #else
26 #include <stdint.h>
27 #endif
28
29 /* size of read buffer */
30 #define SIZE 0x1000
31
32 /* PPCBUG ROM boot header */
33 typedef struct bug_boot_header {
34   uint8_t       magic_word[4];          /* "BOOT" */
35   uint32_t      entry_offset;           /* Offset from top of header to code */
36   uint32_t      routine_length;         /* Length of code */
37   uint8_t       routine_name[8];        /* Name of the boot code */
38 } bug_boot_header_t;
39
40 #define HEADER_SIZE     sizeof(bug_boot_header_t)
41
42 void update_checksum(void *buf, size_t size, uint16_t *sum)
43 {
44         uint32_t csum = *sum;
45
46         while (size) {
47                 csum += *(uint16_t *)buf;
48                 if (csum > 0xffff)
49                         csum -= 0xffff;
50                 buf = (uint16_t *)buf + 1;
51                 size -= 2;
52         }
53         *sum = csum;
54 }
55
56 uint32_t copy_image(int in_fd, int out_fd, uint16_t *sum)
57 {
58         uint8_t buf[SIZE];
59         int offset = 0;
60         int n;
61         uint32_t image_size = 0;
62
63         lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET);
64
65         /* Copy an image while recording its size */
66         while ( (n = read(in_fd, buf + offset, SIZE - offset)) > 0 ) {
67                 n += offset;
68                 offset = n & 1;
69                 n -= offset;
70                 image_size = image_size + n;
71                 /* who's going to deal with short writes? */
72                 write(out_fd, buf, n);
73                 update_checksum(buf, n, sum);
74                 if (offset)
75                         buf[0] = buf[n];
76         }
77
78         /* BUG romboot requires that our size is divisible by 2 */
79         /* align image to 2 byte boundary */
80         if (offset) {
81                 image_size += 2;
82                 buf[1] = '\0';
83                 write(out_fd, buf, 2);
84                 update_checksum(buf, 2, sum);
85         }
86         return image_size;
87 }
88
89 void write_bugboot_header(int out_fd, uint32_t boot_size, uint16_t *sum)
90 {
91         static bug_boot_header_t bbh = {
92                 .magic_word = "BOOT",
93                 .routine_name = "LINUXROM"
94         };
95
96         /* Fill in the PPCBUG ROM boot header */
97         bbh.entry_offset = htonl(HEADER_SIZE);  /* Entry address */
98         bbh.routine_length= htonl(HEADER_SIZE+boot_size+2);     /* Routine length */
99
100         /* Output the header and bootloader to the file */
101         write(out_fd, &bbh, sizeof(bug_boot_header_t));
102         update_checksum(&bbh, sizeof(bug_boot_header_t), sum);
103 }
104
105 int main(int argc, char *argv[])
106 {
107         int image_fd, bugboot_fd;
108         uint32_t kernel_size = 0;
109         uint16_t checksum = 0;
110
111         if (argc != 3) {
112                 fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]);
113                 exit(-1);
114         }
115
116         /* Get file args */
117
118         /* kernel image file */
119         if ((image_fd = open(argv[1] , 0)) < 0)
120                 exit(-1);
121
122         /* bugboot file */
123         if (!strcmp(argv[2], "-"))
124                 bugboot_fd = 1;                 /* stdout */
125         else if ((bugboot_fd = creat(argv[2] , 0755)) < 0)
126                 exit(-1);
127
128         /* Set file position after ROM header block where zImage will be written */
129         lseek(bugboot_fd, HEADER_SIZE, SEEK_SET);
130
131         /* Copy kernel image into bugboot image */
132         kernel_size = copy_image(image_fd, bugboot_fd, &checksum);
133
134         /* Set file position to beginning where header/romboot will be written */
135         lseek(bugboot_fd, 0, SEEK_SET);
136
137         /* Write out BUG header/romboot */
138         write_bugboot_header(bugboot_fd, kernel_size, &checksum);
139
140         /* Write out the calculated checksum */
141         lseek(bugboot_fd, 0, SEEK_END);
142         write(bugboot_fd, &checksum, 2);
143
144         /* Close bugboot file */
145         close(bugboot_fd);
146         return 0;
147 }