linux-old/arch/ppc/boot/utils/addnote.c
<<
>>
Prefs
   1/*
   2 * Program to hack in a PT_NOTE program header entry in an ELF file.
   3 * This is needed for OF on RS/6000s to load an image correctly.
   4 * Note that OF needs a program header entry for the note, not an
   5 * ELF section.
   6 *
   7 * Copyright 2000 Paul Mackerras.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License
  11 * as published by the Free Software Foundation; either version
  12 * 2 of the License, or (at your option) any later version.
  13 *
  14 * Usage: addnote zImage
  15 */
  16#include <stdio.h>
  17#include <fcntl.h>
  18#include <unistd.h>
  19#include <string.h>
  20
  21char arch[] = "PowerPC";
  22
  23#define N_DESCR 6
  24unsigned int descr[N_DESCR] = {
  25#if 1
  26        /* values for IBM RS/6000 machines */
  27        0xffffffff,             /* real-mode = true */
  28        0x00c00000,             /* real-base, i.e. where we expect OF to be */
  29        0xffffffff,             /* real-size */
  30        0xffffffff,             /* virt-base */
  31        0xffffffff,             /* virt-size */
  32        0x4000,                 /* load-base */
  33#else
  34        /* values for longtrail CHRP */
  35        0,                      /* real-mode = false */
  36        0xffffffff,             /* real-base */
  37        0xffffffff,             /* real-size */
  38        0xffffffff,             /* virt-base */
  39        0xffffffff,             /* virt-size */
  40        0x00600000,             /* load-base */
  41#endif
  42};
  43
  44unsigned char buf[512];
  45
  46#define GET_16BE(off)   ((buf[off] << 8) + (buf[(off)+1]))
  47#define GET_32BE(off)   ((GET_16BE(off) << 16) + GET_16BE((off)+2))
  48
  49#define PUT_16BE(off, v)        (buf[off] = ((v) >> 8) & 0xff, \
  50                                 buf[(off) + 1] = (v) & 0xff)
  51#define PUT_32BE(off, v)        (PUT_16BE((off), (v) >> 16), \
  52                                 PUT_16BE((off) + 2, (v)))
  53
  54/* Structure of an ELF file */
  55#define E_IDENT         0       /* ELF header */
  56#define E_PHOFF         28
  57#define E_PHENTSIZE     42
  58#define E_PHNUM         44
  59#define E_HSIZE         52      /* size of ELF header */
  60
  61#define EI_MAGIC        0       /* offsets in E_IDENT area */
  62#define EI_CLASS        4
  63#define EI_DATA         5
  64
  65#define PH_TYPE         0       /* ELF program header */
  66#define PH_OFFSET       4
  67#define PH_FILESZ       16
  68#define PH_HSIZE        32      /* size of program header */
  69
  70#define PT_NOTE         4       /* Program header type = note */
  71
  72#define ELFCLASS32      1
  73#define ELFDATA2MSB     2
  74
  75unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
  76
  77int main(int ac, char **av)
  78{
  79        int fd, n, i;
  80        int ph, ps, np;
  81        int nnote, ns;
  82
  83        if (ac != 2) {
  84                fprintf(stderr, "Usage: %s elf-file\n", av[0]);
  85                exit(1);
  86        }
  87        fd = open(av[1], O_RDWR);
  88        if (fd < 0) {
  89                perror(av[1]);
  90                exit(1);
  91        }
  92
  93        nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
  94
  95        n = read(fd, buf, sizeof(buf));
  96        if (n < 0) {
  97                perror("read");
  98                exit(1);
  99        }
 100
 101        if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
 102                goto notelf;
 103
 104        if (buf[E_IDENT+EI_CLASS] != ELFCLASS32
 105            || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
 106                fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
 107                        av[1]);
 108                exit(1);
 109        }
 110
 111        ph = GET_32BE(E_PHOFF);
 112        ps = GET_16BE(E_PHENTSIZE);
 113        np = GET_16BE(E_PHNUM);
 114        if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
 115                goto notelf;
 116        if (ph + (np + 1) * ps + nnote > n)
 117                goto nospace;
 118
 119        for (i = 0; i < np; ++i) {
 120                if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
 121                        fprintf(stderr, "%s already has a note entry\n",
 122                                av[1]);
 123                        exit(0);
 124                }
 125                ph += ps;
 126        }
 127
 128        /* XXX check that the area we want to use is all zeroes */
 129        for (i = 0; i < ps + nnote; ++i)
 130                if (buf[ph + i] != 0)
 131                        goto nospace;
 132
 133        /* fill in the program header entry */
 134        ns = ph + ps;
 135        PUT_32BE(ph + PH_TYPE, PT_NOTE);
 136        PUT_32BE(ph + PH_OFFSET, ns);
 137        PUT_32BE(ph + PH_FILESZ, nnote);
 138
 139        /* fill in the note area we point to */
 140        /* XXX we should probably make this a proper section */
 141        PUT_32BE(ns, strlen(arch) + 1);
 142        PUT_32BE(ns + 4, N_DESCR * 4);
 143        PUT_32BE(ns + 8, 0x1275);
 144        strcpy(&buf[ns + 12], arch);
 145        ns += 12 + strlen(arch) + 1;
 146        for (i = 0; i < N_DESCR; ++i)
 147                PUT_32BE(ns + i * 4, descr[i]);
 148
 149        /* Update the number of program headers */
 150        PUT_16BE(E_PHNUM, np + 1);
 151
 152        /* write back */
 153        lseek(fd, (long) 0, SEEK_SET);
 154        i = write(fd, buf, n);
 155        if (i < 0) {
 156                perror("write");
 157                exit(1);
 158        }
 159        if (i < n) {
 160                fprintf(stderr, "%s: write truncated\n", av[1]);
 161                exit(1);
 162        }
 163
 164        exit(0);
 165
 166 notelf:
 167        fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]);
 168        exit(1);
 169
 170 nospace:
 171        fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
 172                av[0]);
 173        exit(1);
 174}
 175
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.