aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/boot/addRamDisk.c
diff options
context:
space:
mode:
authorOlaf Hering <olh@suse.de>2005-11-09 14:53:43 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-09 19:25:52 -0500
commit681c774d0fb59c9b9525c2879d1cfae29c2f7866 (patch)
treed3794a02c0699f656d284d65b6c7403ca8407085 /arch/ppc64/boot/addRamDisk.c
parent58638bffe3d594ed3a902824ea40a4196c745bbd (diff)
[PATCH] ppc64 boot: remove sysmap from required filenames
A stripped vmlinux does not contain enough symbols to recreate the System.map. The System.map file is only used to determine the end of the runtime memory size. This is the same value (rounded up to PAGE_SIZE) as ->memsiz in the ELF program header. Also, the target vmlinux.initrd doesnt work in 2.6.14: arch/ppc64/boot/addRamDisk arch/ppc64/boot/ramdisk.image.gz vmlinux.strip arch/ppc64/boot/vmlinux.initrd Name of vmlinux output file missing. Signed-off-by: Olaf Hering <olh@suse.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc64/boot/addRamDisk.c')
-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