aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/boot/addRamDisk.c131
1 files changed, 69 insertions, 62 deletions
diff --git a/arch/ppc64/boot/addRamDisk.c b/arch/ppc64/boot/addRamDisk.c
index c10746a187b6..d99c04a38e46 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,21 +82,17 @@ 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];
85 struct addr_range vmlinux;
37 FILE *ramDisk; 86 FILE *ramDisk;
38 FILE *sysmap;
39 FILE *inputVmlinux; 87 FILE *inputVmlinux;
40 FILE *outputVmlinux; 88 FILE *outputVmlinux;
41 89
42 char *rd_name, *lx_name, *out_name; 90 char *rd_name, *lx_name, *out_name;
43 unsigned i; 91
92 size_t i;
44 unsigned long ramFileLen; 93 unsigned long ramFileLen;
45 unsigned long ramLen; 94 unsigned long ramLen;
46 unsigned long roundR; 95 unsigned long roundR;
47
48 unsigned long sysmapFileLen;
49 unsigned long sysmapLen;
50 unsigned long sysmapPages;
51 char *ptr_end;
52 unsigned long offset_end; 96 unsigned long offset_end;
53 97
54 unsigned long kernelLen; 98 unsigned long kernelLen;
@@ -70,24 +114,19 @@ int main(int argc, char **argv)
70 fprintf(stderr, "Name of RAM disk file missing.\n"); 114 fprintf(stderr, "Name of RAM disk file missing.\n");
71 exit(1); 115 exit(1);
72 } 116 }
73 rd_name = argv[1] 117 rd_name = argv[1];
74 118
75 if (argc < 3) { 119 if (argc < 3) {
76 fprintf(stderr, "Name of System Map input file is missing.\n");
77 exit(1);
78 }
79
80 if (argc < 4) {
81 fprintf(stderr, "Name of vmlinux file missing.\n"); 120 fprintf(stderr, "Name of vmlinux file missing.\n");
82 exit(1); 121 exit(1);
83 } 122 }
84 lx_name = argv[3]; 123 lx_name = argv[2];
85 124
86 if (argc < 5) { 125 if (argc < 4) {
87 fprintf(stderr, "Name of vmlinux output file missing.\n"); 126 fprintf(stderr, "Name of vmlinux output file missing.\n");
88 exit(1); 127 exit(1);
89 } 128 }
90 out_name = argv[4]; 129 out_name = argv[3];
91 130
92 131
93 ramDisk = fopen(rd_name, "r"); 132 ramDisk = fopen(rd_name, "r");
@@ -96,12 +135,6 @@ int main(int argc, char **argv)
96 exit(1); 135 exit(1);
97 } 136 }
98 137
99 sysmap = fopen(argv[2], "r");
100 if ( ! sysmap ) {
101 fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[2]);
102 exit(1);
103 }
104
105 inputVmlinux = fopen(lx_name, "r"); 138 inputVmlinux = fopen(lx_name, "r");
106 if ( ! inputVmlinux ) { 139 if ( ! inputVmlinux ) {
107 fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name); 140 fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name);
@@ -113,18 +146,24 @@ int main(int argc, char **argv)
113 fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name); 146 fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name);
114 exit(1); 147 exit(1);
115 } 148 }
116 149
117 150 i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux);
118 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
119 /* Input Vmlinux file */ 162 /* Input Vmlinux file */
120 fseek(inputVmlinux, 0, SEEK_END); 163 fseek(inputVmlinux, 0, SEEK_END);
121 kernelLen = ftell(inputVmlinux); 164 kernelLen = ftell(inputVmlinux);
122 fseek(inputVmlinux, 0, SEEK_SET); 165 fseek(inputVmlinux, 0, SEEK_SET);
123 printf("kernel file size = %d\n", kernelLen); 166 printf("kernel file size = %d\n", kernelLen);
124 if ( kernelLen == 0 ) {
125 fprintf(stderr, "You must have a linux kernel specified as argv[3]\n");
126 exit(1);
127 }
128 167
129 actualKernelLen = kernelLen - ElfHeaderSize; 168 actualKernelLen = kernelLen - ElfHeaderSize;
130 169
@@ -138,39 +177,7 @@ int main(int argc, char **argv)
138 roundedKernelPages = roundedKernelLen / 4096; 177 roundedKernelPages = roundedKernelLen / 4096;
139 printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages); 178 printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
140 179
141 180 offset_end = _ALIGN_UP(vmlinux.memsize, 4096);
142
143 /* Input System Map file */
144 /* (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) */
145 fseek(sysmap, 0, SEEK_END);
146 sysmapFileLen = ftell(sysmap);
147 fseek(sysmap, 0, SEEK_SET);
148 printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen);
149
150 sysmapLen = sysmapFileLen;
151
152 roundR = 4096 - (sysmapLen % 4096);
153 if (roundR) {
154 printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
155 sysmapLen += roundR;
156 }
157 printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen);
158
159 /* Process the Sysmap file to determine where _end is */
160 sysmapPages = sysmapLen / 4096;
161 /* read the whole file line by line, expect that it doesn't fail */
162 while ( fgets(inbuf, 4096, sysmap) ) ;
163 /* search for _end in the last page of the system map */
164 ptr_end = strstr(inbuf, " _end");
165 if (!ptr_end) {
166 fprintf(stderr, "Unable to find _end in the sysmap file \n");
167 fprintf(stderr, "inbuf: \n");
168 fprintf(stderr, "%s \n", inbuf);
169 exit(1);
170 }
171 printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10);
172 /* convert address of _end in system map to hex offset. */
173 offset_end = (unsigned int)strtol(ptr_end-10, NULL, 16);
174 /* 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 */
175 padPages = offset_end/4096 - roundedKernelPages; 182 padPages = offset_end/4096 - roundedKernelPages;
176 183