]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/ppc64/boot/addRamDisk.c
[PATCH] ppc64 boot: remove sysmap from required filenames
[karo-tx-linux.git] / 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;