[PATCH] ppc64 boot: remove sysmap from required filenames
authorOlaf Hering <olh@suse.de>
Wed, 9 Nov 2005 19:53:43 +0000 (20:53 +0100)
committerPaul Mackerras <paulus@samba.org>
Thu, 10 Nov 2005 00:25:52 +0000 (11:25 +1100)
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>
arch/ppc64/boot/addRamDisk.c

index c10746a187b636c6df725bc571b2cb916f70ff22..d99c04a38e4673764b384cc3fa31726367150965 100644 (file)
@@ -5,11 +5,59 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <string.h>
+#include <elf.h>
 
 #define ElfHeaderSize  (64 * 1024)
 #define ElfPages  (ElfHeaderSize / 4096)
 #define KERNELBASE (0xc000000000000000)
+#define _ALIGN_UP(addr,size)   (((addr)+((size)-1))&(~((size)-1)))
 
+struct addr_range {
+       unsigned long long addr;
+       unsigned long memsize;
+       unsigned long offset;
+};
+
+static int check_elf64(void *p, int size, struct addr_range *r)
+{
+       Elf64_Ehdr *elf64 = p;
+       Elf64_Phdr *elf64ph;
+
+       if (elf64->e_ident[EI_MAG0] != ELFMAG0 ||
+           elf64->e_ident[EI_MAG1] != ELFMAG1 ||
+           elf64->e_ident[EI_MAG2] != ELFMAG2 ||
+           elf64->e_ident[EI_MAG3] != ELFMAG3 ||
+           elf64->e_ident[EI_CLASS] != ELFCLASS64 ||
+           elf64->e_ident[EI_DATA] != ELFDATA2MSB ||
+           elf64->e_type != ET_EXEC || elf64->e_machine != EM_PPC64)
+               return 0;
+
+       if ((elf64->e_phoff + sizeof(Elf64_Phdr)) > size)
+               return 0;
+
+       elf64ph = (Elf64_Phdr *) ((unsigned long)elf64 +
+                                 (unsigned long)elf64->e_phoff);
+
+       r->memsize = (unsigned long)elf64ph->p_memsz;
+       r->offset = (unsigned long)elf64ph->p_offset;
+       r->addr = (unsigned long long)elf64ph->p_vaddr;
+
+#ifdef DEBUG
+       printf("PPC64 ELF file, ph:\n");
+       printf("p_type   0x%08x\n", elf64ph->p_type);
+       printf("p_flags  0x%08x\n", elf64ph->p_flags);
+       printf("p_offset 0x%016llx\n", elf64ph->p_offset);
+       printf("p_vaddr  0x%016llx\n", elf64ph->p_vaddr);
+       printf("p_paddr  0x%016llx\n", elf64ph->p_paddr);
+       printf("p_filesz 0x%016llx\n", elf64ph->p_filesz);
+       printf("p_memsz  0x%016llx\n", elf64ph->p_memsz);
+       printf("p_align  0x%016llx\n", elf64ph->p_align);
+       printf("... skipping 0x%08lx bytes of ELF header\n",
+              (unsigned long)elf64ph->p_offset);
+#endif
+
+       return 64;
+}
 void get4k(FILE *file, char *buf )
 {
        unsigned j;
@@ -34,21 +82,17 @@ void death(const char *msg, FILE *fdesc, const char *fname)
 int main(int argc, char **argv)
 {
        char inbuf[4096];
+       struct addr_range vmlinux;
        FILE *ramDisk;
-       FILE *sysmap;
        FILE *inputVmlinux;
        FILE *outputVmlinux;
 
        char *rd_name, *lx_name, *out_name;
-       unsigned i;
+
+       size_t i;
        unsigned long ramFileLen;
        unsigned long ramLen;
        unsigned long roundR;
-
-       unsigned long sysmapFileLen;
-       unsigned long sysmapLen;
-       unsigned long sysmapPages;
-       char *ptr_end;
        unsigned long offset_end;
 
        unsigned long kernelLen;
@@ -70,24 +114,19 @@ int main(int argc, char **argv)
                fprintf(stderr, "Name of RAM disk file missing.\n");
                exit(1);
        }
-       rd_name = argv[1]
+       rd_name = argv[1];
 
        if (argc < 3) {
-               fprintf(stderr, "Name of System Map input file is missing.\n");
-               exit(1);
-       }
-  
-       if (argc < 4) {
                fprintf(stderr, "Name of vmlinux file missing.\n");
                exit(1);
        }
-       lx_name = argv[3];
+       lx_name = argv[2];
 
-       if (argc < 5) {
+       if (argc < 4) {
                fprintf(stderr, "Name of vmlinux output file missing.\n");
                exit(1);
        }
-       out_name = argv[4];
+       out_name = argv[3];
 
 
        ramDisk = fopen(rd_name, "r");
@@ -96,12 +135,6 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       sysmap = fopen(argv[2], "r");
-       if ( ! sysmap ) {
-               fprintf(stderr, "System Map file \"%s\" failed to open.\n", argv[2]);
-               exit(1);
-       }
-  
        inputVmlinux = fopen(lx_name, "r");
        if ( ! inputVmlinux ) {
                fprintf(stderr, "vmlinux file \"%s\" failed to open.\n", lx_name);
@@ -113,18 +146,24 @@ int main(int argc, char **argv)
                fprintf(stderr, "output vmlinux file \"%s\" failed to open.\n", out_name);
                exit(1);
        }
-  
-  
-  
+
+       i = fread(inbuf, 1, sizeof(inbuf), inputVmlinux);
+       if (i != sizeof(inbuf)) {
+               fprintf(stderr, "can not read vmlinux file %s: %u\n", lx_name, i);
+               exit(1);
+       }
+
+       i = check_elf64(inbuf, sizeof(inbuf), &vmlinux);
+       if (i == 0) {
+               fprintf(stderr, "You must have a linux kernel specified as argv[2]\n");
+               exit(1);
+       }
+
        /* Input Vmlinux file */
        fseek(inputVmlinux, 0, SEEK_END);
        kernelLen = ftell(inputVmlinux);
        fseek(inputVmlinux, 0, SEEK_SET);
        printf("kernel file size = %d\n", kernelLen);
-       if ( kernelLen == 0 ) {
-               fprintf(stderr, "You must have a linux kernel specified as argv[3]\n");
-               exit(1);
-       }
 
        actualKernelLen = kernelLen - ElfHeaderSize;
 
@@ -138,39 +177,7 @@ int main(int argc, char **argv)
        roundedKernelPages = roundedKernelLen / 4096;
        printf("Vmlinux pages to copy = %ld/0x%lx \n", roundedKernelPages, roundedKernelPages);
 
-
-
-       /* Input System Map file */
-       /* (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) */
-       fseek(sysmap, 0, SEEK_END);
-       sysmapFileLen = ftell(sysmap);
-       fseek(sysmap, 0, SEEK_SET);
-       printf("%s file size = %ld/0x%lx \n", argv[2], sysmapFileLen, sysmapFileLen);
-
-       sysmapLen = sysmapFileLen;
-
-       roundR = 4096 - (sysmapLen % 4096);
-       if (roundR) {
-               printf("Rounding System Map file up to a multiple of 4096, adding %ld/0x%lx \n", roundR, roundR);
-               sysmapLen += roundR;
-       }
-       printf("Rounded System Map size is %ld/0x%lx \n", sysmapLen, sysmapLen);
-  
-       /* Process the Sysmap file to determine where _end is */
-       sysmapPages = sysmapLen / 4096;
-       /* read the whole file line by line, expect that it doesn't fail */
-       while ( fgets(inbuf, 4096, sysmap) )  ;
-       /* search for _end in the last page of the system map */
-       ptr_end = strstr(inbuf, " _end");
-       if (!ptr_end) {
-               fprintf(stderr, "Unable to find _end in the sysmap file \n");
-               fprintf(stderr, "inbuf: \n");
-               fprintf(stderr, "%s \n", inbuf);
-               exit(1);
-       }
-       printf("Found _end in the last page of the sysmap - backing up 10 characters it looks like %s", ptr_end-10);
-       /* convert address of _end in system map to hex offset. */
-       offset_end = (unsigned int)strtol(ptr_end-10, NULL, 16);
+       offset_end = _ALIGN_UP(vmlinux.memsize, 4096);
        /* calc how many pages we need to insert between the vmlinux and the start of the ram disk */
        padPages = offset_end/4096 - roundedKernelPages;