aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/boot/addRamDisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/boot/addRamDisk.c')
-rw-r--r--arch/ppc64/boot/addRamDisk.c207
1 files changed, 109 insertions, 98 deletions
diff --git a/arch/ppc64/boot/addRamDisk.c b/arch/ppc64/boot/addRamDisk.c
index 7f2c09473394..c02a99952be7 100644
--- a/arch/ppc64/boot/addRamDisk.c
+++ b/arch/ppc64/boot/addRamDisk.c
@@ -5,11 +5,59 @@
5#include <sys/types.h> 5#include <sys/types.h>
6#include <sys/stat.h> 6#include <sys/stat.h>
7#include <string.h> 7#include <string.h>
8#include <elf.h>
8 9
9#define ElfHeaderSize (64 * 1024) 10#define ElfHeaderSize (64 * 1024)
10#define ElfPages (ElfHeaderSize / 4096) 11#define ElfPages (ElfHeaderSize / 4096)
11#define KERNELBASE (0xc000000000000000) 12#define KERNELBASE (0xc000000000000000)
13#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1)))
12 14
15struct addr_range {
16 unsigned long long addr;
17 unsigned long memsize;
18 unsigned long offset;
19};
20
21static int check_elf64(void *p, int size, struct addr_range *r)
22{
23 Elf64_Ehdr *elf64 = p;
24 Elf64_Phdr *elf64ph;
25
26 if (elf64->e_ident[EI_MAG0] != ELFMAG0 ||
27 elf64->e_ident[EI_MAG1] != ELFMAG1 ||
28 elf64->e_ident[EI_MAG2] != ELFMAG2 ||
29 elf64->e_ident[EI_MAG3] != ELFMAG3 ||
30 elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
31 elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
32 elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64)
33 return 0;
34
35 if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size)
36 return 0;
37
38 elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 +
39 (unsigned long)elf64->e_phoff);
40
41 r->memsize = (unsigned long)elf64ph->p_memsz;
42 r->offset = (unsigned long)elf64ph->p_offset;
43 r->addr = (unsigned long long)elf64ph->p_vaddr;
44
45#ifdef DEBUG
46 printf("PPC64 ELF file, ph:\n");
47 printf("p_type 0x%08x\n", elf64ph->p_type);
48 printf("p_flags 0x%08x\n", elf64ph->p_flags);
49 printf("p_offset 0x%016llx\n", elf64ph->p_offset);
50 printf("p_vaddr 0x%016llx\n", elf64ph->p_vaddr);
51 printf("p_paddr 0x%016llx\n", elf64ph->p_paddr);
52 printf("p_filesz 0x%016llx\n", elf64ph->p_filesz);
53 printf("p_memsz 0x%016llx\n", elf64ph->p_memsz);
54 printf("p_align 0x%016llx\n", elf64ph->p_align);
55 printf("... skipping 0x%08lx bytes of ELF header\n",
56 (unsigned long)elf64ph->p_offset);
57#endif
58
59 return 64;
60}
13void get4k(FILE *file, char *buf ) 61void get4k(FILE *file, char *buf )
14{ 62{
15 unsigned j; 63 unsigned j;
@@ -34,97 +82,92 @@ void death(const char *msg, FILE *fdesc, const char *fname)
34int main(int argc, char **argv) 82int main(int argc, char **argv)
35{ 83{
36 char inbuf[4096]; 84 char inbuf[4096];
37 FILE *ramDisk = NULL; 85 struct addr_range vmlinux;
38 FILE *sysmap = NULL; 86 FILE *ramDisk;
39 FILE *inputVmlinux = NULL; 87 FILE *inputVmlinux;
40 FILE *outputVmlinux = NULL; 88 FILE *outputVmlinux;
41 89
42 unsigned i = 0; 90 char *rd_name, *lx_name, *out_name;
43 unsigned long ramFileLen = 0; 91
44 unsigned long ramLen = 0; 92 size_t i;
45 unsigned long roundR = 0; 93 unsigned long ramFileLen;
46 94 unsigned long ramLen;
47 unsigned long sysmapFileLen = 0; 95 unsigned long roundR;
48 unsigned long sysmapLen = 0; 96 unsigned long offset_end;
49 unsigned long sysmapPages = 0; 97
50 char* ptr_end = NULL; 98 unsigned long kernelLen;
51 unsigned long offset_end = 0; 99 unsigned long actualKernelLen;
52 100 unsigned long round;
53 unsigned long kernelLen = 0; 101 unsigned long roundedKernelLen;
54 unsigned long actualKernelLen = 0; 102 unsigned long ramStartOffs;
55 unsigned long round = 0; 103 unsigned long ramPages;
56 unsigned long roundedKernelLen = 0; 104 unsigned long roundedKernelPages;
57 unsigned long ramStartOffs = 0; 105 unsigned long hvReleaseData;
58 unsigned long ramPages = 0;
59 unsigned long roundedKernelPages = 0;
60 unsigned long hvReleaseData = 0;
61 u_int32_t eyeCatcher = 0xc8a5d9c4; 106 u_int32_t eyeCatcher = 0xc8a5d9c4;
62 unsigned long naca = 0; 107 unsigned long naca;
63 unsigned long xRamDisk = 0; 108 unsigned long xRamDisk;
64 unsigned long xRamDiskSize = 0; 109 unsigned long xRamDiskSize;
65 long padPages = 0; 110 long padPages;
66 111
67 112
68 if (argc < 2) { 113 if (argc < 2) {
69 fprintf(stderr, "Name of RAM disk file missing.\n"); 114 fprintf(stderr, "Name of RAM disk file missing.\n");
70 exit(1); 115 exit(1);
71 } 116 }
117 rd_name = argv[1];
72 118
73 if (argc < 3) { 119 if (argc < 3) {
74 fprintf(stderr, "Name of System Map input file is missing.\n");
75 exit(1);
76 }
77
78 if (argc < 4) {
79 fprintf(stderr, "Name of vmlinux file missing.\n"); 120 fprintf(stderr, "Name of vmlinux file missing.\n");
80 exit(1); 121 exit(1);
81 } 122 }
123 lx_name = argv[2];
82 124
83 if (argc < 5) { 125 if (argc < 4) {
84 fprintf(stderr, "Name of vmlinux output file missing.\n"); 126 fprintf(stderr, "Name of vmlinux output file missing.\n");
85 exit(1); 127 exit(1);
86 } 128 }
129 out_name = argv[3];
87 130
88 131
89 ramDisk = fopen(argv[1], "r"); 132 ramDisk = fopen(rd_name, "r");
90 if ( ! ramDisk ) { 133 if ( ! ramDisk ) {
91 fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", argv[1]); 134 fprintf(stderr, "RAM disk file \"%s\" failed to open.\n", rd_name);
92 exit(1); 135 exit(1);
93 } 136 }
94 137
95 sysmap = fopen(argv[2], "r"); 138 inputVmlinux = fopen(lx_name, "r");
96 if ( ! sysmap ) {
97 fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[2]);
98 exit(1);
99 }
100
101 inputVmlinux = fopen(argv[3], "r");
102 if ( ! inputVmlinux ) { 139 if ( ! inputVmlinux ) {
103 fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", argv[3]); 140 fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name);
104 exit(1); 141 exit(1);
105 } 142 }
106 143
107 outputVmlinux = fopen(argv[4], "w+"); 144 outputVmlinux = fopen(out_name, "w+");
108 if ( ! outputVmlinux ) { 145 if ( ! outputVmlinux ) {
109 fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", argv[4]); 146 fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name);
110 exit(1); 147 exit(1);
111 } 148 }
112 149
113 150 i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux);
114 151 if (i != sizeof(inbuf)) {
152 fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i);
153 exit(1);
154 }
155
156 i = check_elf64(inbuf, sizeof(inbuf), &vmlinux);
157 if (i == 0) {
158 fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
159 exit(1);
160 }
161
115 /* Input Vmlinux file */ 162 /* Input Vmlinux file */
116 fseek(inputVmlinux, 0, SEEK_END); 163 fseek(inputVmlinux, 0, SEEK_END);
117 kernelLen = ftell(inputVmlinux); 164 kernelLen = ftell(inputVmlinux);
118 fseek(inputVmlinux, 0, SEEK_SET); 165 fseek(inputVmlinux, 0, SEEK_SET);
119 printf("kernel file size = %d\n", kernelLen); 166 printf("kernel file size = %lu\n", kernelLen);
120 if ( kernelLen == 0 ) {
121 fprintf(stderr, "You must have a linux kernel specified as argv[3]\n");
122 exit(1);
123 }
124 167
125 actualKernelLen = kernelLen - ElfHeaderSize; 168 actualKernelLen = kernelLen - ElfHeaderSize;
126 169
127 printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen); 170 printf("actual kernel length (minus ELF header) = %lu\n", actualKernelLen);
128 171
129 round = actualKernelLen % 4096; 172 round = actualKernelLen % 4096;
130 roundedKernelLen = actualKernelLen; 173 roundedKernelLen = actualKernelLen;
@@ -134,39 +177,7 @@ int main(int argc, char **argv)
134 roundedKernelPages = roundedKernelLen / 4096; 177 roundedKernelPages = roundedKernelLen / 4096;
135 printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); 178 printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
136 179
137 180 offset_end = _ALIGN_UP(vmlinux.memsize, 4096);
138
139 /* Input System Map file */
140 /* (needs to be processed simply to determine if we need to add pad pages due to the static variables not being included in the vmlinux) */
141 fseek(sysmap, 0, SEEK_END);
142 sysmapFileLen = ftell(sysmap);
143 fseek(sysmap, 0, SEEK_SET);
144 printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen);
145
146 sysmapLen = sysmapFileLen;
147
148 roundR = 4096 - (sysmapLen % 4096);
149 if (roundR) {
150 printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
151 sysmapLen += roundR;
152 }
153 printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen);
154
155 /* Process the Sysmap file to determine where _end is */
156 sysmapPages = sysmapLen / 4096;
157 /* read the whole file line by line, expect that it doesn't fail */
158 while ( fgets(inbuf, 4096, sysmap) ) ;
159 /* search for _end in the last page of the system map */
160 ptr_end = strstr(inbuf, " _end");
161 if (!ptr_end) {
162 fprintf(stderr, "Unable to find _end in the sysmap file \n");
163 fprintf(stderr, "inbuf: \n");
164 fprintf(stderr, "%s \n", inbuf);
165 exit(1);
166 }
167 printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10);
168 /* convert address of _end in system map to hex offset. */
169 offset_end = (unsigned int)strtol(ptr_end-10, NULL, 16);
170 /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */ 181 /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */
171 padPages = offset_end/4096 - roundedKernelPages; 182 padPages = offset_end/4096 - roundedKernelPages;
172 183
@@ -194,7 +205,7 @@ int main(int argc, char **argv)
194 fseek(ramDisk, 0, SEEK_END); 205 fseek(ramDisk, 0, SEEK_END);
195 ramFileLen = ftell(ramDisk); 206 ramFileLen = ftell(ramDisk);
196 fseek(ramDisk, 0, SEEK_SET); 207 fseek(ramDisk, 0, SEEK_SET);
197 printf("%s file size = %ld/0x%lx \n", argv[1], ramFileLen, ramFileLen); 208 printf("%s file size = %ld/0x%lx \n", rd_name, ramFileLen, ramFileLen);
198 209
199 ramLen = ramFileLen; 210 ramLen = ramFileLen;
200 211
@@ -248,19 +259,19 @@ int main(int argc, char **argv)
248 /* fseek to the hvReleaseData pointer */ 259 /* fseek to the hvReleaseData pointer */
249 fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); 260 fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET);
250 if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { 261 if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) {
251 death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[4]); 262 death("Could not read hvReleaseData pointer\n", outputVmlinux, out_name);
252 } 263 }
253 hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ 264 hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */
254 printf("hvReleaseData is at %08x\n", hvReleaseData); 265 printf("hvReleaseData is at %08lx\n", hvReleaseData);
255 266
256 /* fseek to the hvReleaseData */ 267 /* fseek to the hvReleaseData */
257 fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); 268 fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET);
258 if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { 269 if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) {
259 death("Could not read hvReleaseData\n", outputVmlinux, argv[4]); 270 death("Could not read hvReleaseData\n", outputVmlinux, out_name);
260 } 271 }
261 /* Check hvReleaseData sanity */ 272 /* Check hvReleaseData sanity */
262 if (memcmp(inbuf, &eyeCatcher, 4) != 0) { 273 if (memcmp(inbuf, &eyeCatcher, 4) != 0) {
263 death("hvReleaseData is invalid\n", outputVmlinux, argv[4]); 274 death("hvReleaseData is invalid\n", outputVmlinux, out_name);
264 } 275 }
265 /* Get the naca pointer */ 276 /* Get the naca pointer */
266 naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE; 277 naca = ntohl(*((u_int32_t*) &inbuf[0x0C])) - KERNELBASE;
@@ -269,13 +280,13 @@ int main(int argc, char **argv)
269 /* fseek to the naca */ 280 /* fseek to the naca */
270 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); 281 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
271 if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { 282 if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) {
272 death("Could not read naca\n", outputVmlinux, argv[4]); 283 death("Could not read naca\n", outputVmlinux, out_name);
273 } 284 }
274 xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); 285 xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c]));
275 xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); 286 xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14]));
276 /* Make sure a RAM disk isn't already present */ 287 /* Make sure a RAM disk isn't already present */
277 if ((xRamDisk != 0) || (xRamDiskSize != 0)) { 288 if ((xRamDisk != 0) || (xRamDiskSize != 0)) {
278 death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[4]); 289 death("RAM disk is already attached to this kernel\n", outputVmlinux, out_name);
279 } 290 }
280 /* Fill in the values */ 291 /* Fill in the values */
281 *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); 292 *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs);
@@ -285,15 +296,15 @@ int main(int argc, char **argv)
285 fflush(outputVmlinux); 296 fflush(outputVmlinux);
286 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); 297 fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET);
287 if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { 298 if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) {
288 death("Could not write naca\n", outputVmlinux, argv[4]); 299 death("Could not write naca\n", outputVmlinux, out_name);
289 } 300 }
290 printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08x\n", 301 printf("Ram Disk of 0x%lx pages is attached to the kernel at offset 0x%08lx\n",
291 ramPages, ramStartOffs); 302 ramPages, ramStartOffs);
292 303
293 /* Done */ 304 /* Done */
294 fclose(outputVmlinux); 305 fclose(outputVmlinux);
295 /* Set permission to executable */ 306 /* Set permission to executable */
296 chmod(argv[4], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); 307 chmod(out_name, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
297 308
298 return 0; 309 return 0;
299} 310}