mboot.patch

 
   1  diff -urbN linux/arch/i386/Makefile linux.new/arch/i386/Makefile
   2  --- linux/arch/i386/Makefile    Thu Apr 12 21:20:31 2001
   3  +++ linux.new/arch/i386/Makefile        Wed Nov 28 00:26:22 2001
   4  @@ -18,7 +18,7 @@
   5
   6   LD=$(CROSS_COMPILE)ld -m elf_i386
   7   OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
   8  -LDFLAGS=-e stext
   9  +LDFLAGS=
  10   LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
  11
  12   CFLAGS += -pipe
  13  diff -urbN linux/arch/i386/kernel/Makefile linux.new/arch/i386/kernel/Makefile
  14  --- linux/arch/i386/kernel/Makefile     Tue Sep 18 08:03:09 2001
  15  +++ linux.new/arch/i386/kernel/Makefile Wed Dec  5 22:12:44 2001
  16  @@ -18,7 +18,8 @@
  17
  18   obj-y  := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
  19                  ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
  20  -               pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
  21  +               pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o \
  22  +               obj_i386.o
  23
  24
  25   ifdef CONFIG_PCI
  26  diff -urbN linux/arch/i386/kernel/head.S linux.new/arch/i386/kernel/head.S
  27  --- linux/arch/i386/kernel/head.S       Wed Jun 20 20:00:53 2001
  28  +++ linux.new/arch/i386/kernel/head.S   Fri Nov 30 21:40:30 2001
  29  @@ -7,6 +7,9 @@
  30    *  and Martin Mares, November 1997.
  31    */
  32
  33  +#define ASM    1
  34  +#include <asm/multiboot.h>
  35  +
  36   .text
  37   #include <linux/config.h>
  38   #include <linux/threads.h>
  39  @@ -45,12 +48,36 @@
  40   /*
  41    * Set segments to known values
  42    */
  43  -       cld
  44          movl $(__KERNEL_DS),%eax
  45          movl %eax,%ds
  46          movl %eax,%es
  47          movl %eax,%fs
  48          movl %eax,%gs
  49  +       movl %eax,%ss
  50  +
  51  +       jmp     real_startup_32
  52  +
  53  +       /* Align 32 bits boundary.  */
  54  +       .align  4
  55  +
  56  +       /* Multiboot header.  */
  57  +multiboot_header:
  58  +
  59  +       /* magic */
  60  +       .long   MULTIBOOT_HEADER_MAGIC
  61  +       /* flags */
  62  +       .long   MULTIBOOT_HEADER_FLAGS
  63  +       /* checksum */
  64  +       .long   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
  65  +
  66  +.globl SYMBOL_NAME(multiboot_entry)
  67  +multiboot_entry:
  68  +       movl %ebx,SYMBOL_NAME(mbootinfo) - __PAGE_OFFSET
  69  +       xorl %ebx,%ebx
  70  +
  71  +real_startup_32:
  72  +
  73  +       cld
  74   #ifdef CONFIG_SMP
  75          orw %bx,%bx
  76          jz 1f
  77  @@ -104,7 +131,7 @@
  78          jmp *%eax               /* make sure eip is relocated */
  79   1:
  80          /* Set up the stack pointer */
  81  -       lss stack_start,%esp
  82  +       movl stack_start,%esp
  83
  84   #ifdef CONFIG_SMP
  85          orw  %bx,%bx
  86  @@ -119,6 +146,10 @@
  87    * Clear BSS first so that there are no surprises...
  88    * No need to cld as DF is already clear from cld above...
  89    */
  90  +       movl SYMBOL_NAME(mbootinfo),%eax
  91  +       andl %eax,%eax
  92  +       jnz 1f                  # We have a multiboot boot loader
  93  +
  94          xorl %eax,%eax
  95          movl $ SYMBOL_NAME(__bss_start),%edi
  96          movl $ SYMBOL_NAME(_end),%ecx
  97  @@ -126,6 +157,8 @@
  98          rep
  99          stosb
 100
 101  +1:
 102  +
 103   /*
 104    * start system 32-bit setup. We need to re-do some of the things done
 105    * in 16-bit mode for the "real" operations.
 106  @@ -145,6 +178,10 @@
 107    *
 108    * Note: %esi still has the pointer to the real-mode data.
 109    */
 110  +       movl SYMBOL_NAME(mbootinfo),%eax
 111  +       andl %eax,%eax
 112  +       jnz 1f                  # We have a multiboot boot loader
 113  +
 114          movl $ SYMBOL_NAME(empty_zero_page),%edi
 115          movl $512,%ecx
 116          cld
 117  @@ -358,6 +395,7 @@
 118
 119   .globl SYMBOL_NAME(idt)
 120   .globl SYMBOL_NAME(gdt)
 121  +.globl SYMBOL_NAME(mbootinfo)
 122
 123          ALIGN
 124          .word 0
 125  @@ -371,6 +409,11 @@
 126          .word GDT_ENTRIES*8-1
 127   SYMBOL_NAME(gdt):
 128          .long SYMBOL_NAME(gdt_table)
 129  +
 130  +       .word 0
 131  +
 132  +SYMBOL_NAME(mbootinfo):
 133  +       .long 0
 134
 135   /*
 136    * This is initialized to create an identity-mapping at 0-8M (for bootup
 137  diff -urbN linux/arch/i386/kernel/obj_i386.c linux.new/arch/i386/kernel/obj_i386.c
 138  --- linux/arch/i386/kernel/obj_i386.c   Thu Jan  1 01:00:00 1970
 139  +++ linux.new/arch/i386/kernel/obj_i386.c       Wed Dec  5 23:24:04 2001
 140  @@ -0,0 +1,235 @@
 141  +/* i386 specific support for Elf loading and relocation.
 142  +   Copyright 1996, 1997 Linux International.
 143  +
 144  +   Contributed by Richard Henderson <rth@tamu.edu>
 145  +
 146  +   This file is part of the Linux modutils.
 147  +
 148  +   This program is free software; you can redistribute it and/or modify it
 149  +   under the terms of the GNU General Public License as published by the
 150  +   Free Software Foundation; either version 2 of the License, or (at your
 151  +   option) any later version.
 152  +
 153  +   This program is distributed in the hope that it will be useful, but
 154  +   WITHOUT ANY WARRANTY; without even the implied warranty of
 155  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 156  +   General Public License for more details.
 157  +
 158  +   You should have received a copy of the GNU General Public License
 159  +   along with this program; if not, write to the Free Software Foundation,
 160  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 161  +
 162  +#ident "$Id: obj_i386.c 1.3 Wed, 26 Sep 2001 14:50:45 +1000 kaos $"
 163  +
 164  +#include <linux/slab.h>
 165  +#include <linux/obj_load.h>
 166  +
 167  +
 168  +/*======================================================================*/
 169  +
 170  +struct i386_got_entry
 171  +{
 172  +  int offset;
 173  +  unsigned offset_done : 1;
 174  +  unsigned reloc_done : 1;
 175  +};
 176  +
 177  +struct i386_file
 178  +{
 179  +  struct obj_file root;
 180  +  struct obj_section *got;
 181  +};
 182  +
 183  +struct i386_symbol
 184  +{
 185  +  struct obj_symbol root;
 186  +  struct i386_got_entry gotent;
 187  +};
 188  +
 189  +
 190  +/*======================================================================*/
 191  +
 192  +struct obj_file *
 193  +arch_new_file (void)
 194  +{
 195  +  struct i386_file *f;
 196  +  f = kmalloc(sizeof(*f), GFP_KERNEL);
 197  +  f->got = NULL;
 198  +  return &f->root;
 199  +}
 200  +
 201  +struct obj_section *
 202  +arch_new_section (void)
 203  +{
 204  +  return kmalloc(sizeof(struct obj_section), GFP_KERNEL);
 205  +}
 206  +
 207  +struct obj_symbol *
 208  +arch_new_symbol (void)
 209  +{
 210  +  struct i386_symbol *sym;
 211  +  sym = kmalloc(sizeof(*sym), GFP_KERNEL);
 212  +  memset(&sym->gotent, 0, sizeof(sym->gotent));
 213  +  return &sym->root;
 214  +}
 215  +
 216  +int
 217  +arch_load_proc_section(struct obj_section *sec, int fp)
 218  +{
 219  +    /* Assume it's just a debugging section that we can safely
 220  +       ignore ...  */
 221  +    sec->contents = NULL;
 222  +
 223  +    return 0;
 224  +}
 225  +
 226  +enum obj_reloc
 227  +arch_apply_relocation (struct obj_file *f,
 228  +                      struct obj_section *targsec,
 229  +                      struct obj_section *symsec,
 230  +                      struct obj_symbol *sym,
 231  +                      Elf32_Rel *rel,
 232  +                      Elf32_Addr v)
 233  +{
 234  +  struct i386_file *ifile = (struct i386_file *)f;
 235  +  struct i386_symbol *isym  = (struct i386_symbol *)sym;
 236  +
 237  +  Elf32_Addr *loc = (Elf32_Addr *)(targsec->contents + rel->r_offset);
 238  +  Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
 239  +  Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
 240  +
 241  +  enum obj_reloc ret = obj_reloc_ok;
 242  +
 243  +  switch (ELF32_R_TYPE(rel->r_info))
 244  +    {
 245  +    case R_386_NONE:
 246  +      break;
 247  +
 248  +    case R_386_32:
 249  +      *loc += v;
 250  +      break;
 251  +
 252  +    case R_386_PLT32:
 253  +    case R_386_PC32:
 254  +      *loc += v - dot;
 255  +      break;
 256  +
 257  +    case R_386_GLOB_DAT:
 258  +    case R_386_JMP_SLOT:
 259  +      *loc = v;
 260  +      break;
 261  +
 262  +    case R_386_RELATIVE:
 263  +      *loc += f->baseaddr;
 264  +      break;
 265  +
 266  +    case R_386_GOTPC:
 267  +//      assert(got != 0);
 268  +      *loc += got - dot;
 269  +      break;
 270  +
 271  +    case R_386_GOT32:
 272  +//      assert(isym != NULL);
 273  +      if (!isym->gotent.reloc_done)
 274  +       {
 275  +         isym->gotent.reloc_done = 1;
 276  +         *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
 277  +       }
 278  +      *loc += isym->gotent.offset;
 279  +      break;
 280  +
 281  +    case R_386_GOTOFF:
 282  +//      assert(got != 0);
 283  +      *loc += v - got;
 284  +      break;
 285  +
 286  +    default:
 287  +      ret = obj_reloc_unhandled;
 288  +      break;
 289  +    }
 290  +
 291  +  return ret;
 292  +}
 293  +
 294  +int
 295  +arch_create_got (struct obj_file *f)
 296  +{
 297  +  struct i386_file *ifile = (struct i386_file *)f;
 298  +  int i, n, offset = 0, gotneeded = 0;
 299  +
 300  +  n = ifile->root.header.e_shnum;
 301  +  for (i = 0; i < n; ++i)
 302  +    {
 303  +      struct obj_section *relsec, *symsec, *strsec;
 304  +      Elf32_Rel *rel, *relend;
 305  +      Elf32_Sym *symtab;
 306  +      const char *strtab;
 307  +
 308  +      relsec = ifile->root.sections[i];
 309  +      if (relsec->header.sh_type != SHT_REL)
 310  +       continue;
 311  +
 312  +      symsec = ifile->root.sections[relsec->header.sh_link];
 313  +      strsec = ifile->root.sections[symsec->header.sh_link];
 314  +
 315  +      rel = (Elf32_Rel *)relsec->contents;
 316  +      relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
 317  +      symtab = (Elf32_Sym *)symsec->contents;
 318  +      strtab = (const char *)strsec->contents;
 319  +
 320  +      for (; rel < relend; ++rel)
 321  +       {
 322  +         struct i386_symbol *intsym;
 323  +
 324  +         switch (ELF32_R_TYPE(rel->r_info))
 325  +           {
 326  +           case R_386_GOTPC:
 327  +           case R_386_GOTOFF:
 328  +             gotneeded = 1;
 329  +           default:
 330  +             continue;
 331  +
 332  +           case R_386_GOT32:
 333  +             break;
 334  +           }
 335  +
 336  +         obj_find_relsym(intsym, f, &ifile->root, rel, symtab, strtab);
 337  +
 338  +         if (!intsym->gotent.offset_done)
 339  +           {
 340  +             intsym->gotent.offset_done = 1;
 341  +             intsym->gotent.offset = offset;
 342  +             offset += 4;
 343  +           }
 344  +       }
 345  +    }
 346  +
 347  +  if (offset > 0 || gotneeded)
 348  +    ifile->got = obj_create_alloced_section(&ifile->root, ".got", 4, offset,
 349  +                                           SHF_WRITE);
 350  +
 351  +  return 1;
 352  +}
 353  +
 354  +int
 355  +arch_init_module (struct obj_file *f, struct module *mod)
 356  +{
 357  +  return 1;
 358  +}
 359  +
 360  +int
 361  +arch_finalize_section_address(struct obj_file *f, Elf32_Addr base)
 362  +{
 363  +  int  i, n = f->header.e_shnum;
 364  +
 365  +  f->baseaddr = base;
 366  +  for (i = 0; i < n; ++i)
 367  +    f->sections[i]->header.sh_addr += base;
 368  +  return 1;
 369  +}
 370  +
 371  +int
 372  +arch_archdata (struct obj_file *fin, struct obj_section *sec)
 373  +{
 374  +  return 0;
 375  +}
 376  diff -urbN linux/arch/i386/kernel/setup.c linux.new/arch/i386/kernel/setup.c
 377  --- linux/arch/i386/kernel/setup.c      Thu Oct 25 22:53:46 2001
 378  +++ linux.new/arch/i386/kernel/setup.c  Thu Dec  6 17:54:03 2001
 379  @@ -108,6 +108,8 @@
 380   #include <asm/dma.h>
 381   #include <asm/mpspec.h>
 382   #include <asm/mmu_context.h>
 383  +#include <asm/multiboot.h>
 384  +
 385   /*
 386    * Machine setup..
 387    */
 388  @@ -156,6 +158,11 @@
 389   static int disable_x86_serial_nr __initdata = 1;
 390   static int disable_x86_fxsr __initdata = 0;
 391
 392  +unsigned long mboot_mem_start;
 393  +unsigned long mboot_mem_end;
 394  +unsigned long mboot_module_start;
 395  +unsigned long mboot_module_end;
 396  +
 397   /*
 398    * This is set up by the setup-routine at boot-time
 399    */
 400  @@ -661,6 +668,28 @@
 401   }
 402
 403   /*
 404  + * Converts the Multiboot Mem-Map into a e820 one.
 405  + */
 406  +static int __init mboot_2_e820_map(struct e820entry * biosmap, int nr_map)
 407  +{
 408  +       struct multiboot_memory_map *addr;
 409  +       addr = (struct multiboot_memory_map *)mbootinfo->mmap_addr;
 410  +
 411  +       while((char *)addr < (mbootinfo->mmap_addr + mbootinfo->mmap_length)) {
 412  +
 413  +               biosmap[nr_map].addr = addr->base_addr_low + ((unsigned long long)addr->base_addr_high << 32);
 414  +               biosmap[nr_map].size = addr->length_low + ((unsigned long long)addr->length_high << 32);
 415  +               biosmap[nr_map].type = addr->type;
 416  +
 417  +               addr = (struct multiboot_memory_map *)
 418  +                       ((char *)addr + addr->size + sizeof (addr->size));
 419  +               nr_map++;
 420  +       }
 421  +
 422  +       return nr_map;
 423  +}
 424  +
 425  +/*
 426    * Do NOT EVER look at the BIOS memory size location.
 427    * It does not work on many machines.
 428    */
 429  @@ -676,10 +705,18 @@
 430           * Otherwise fake a memory map; one section from 0k->640k,
 431           * the next section from 1mb->appropriate_mem_k
 432           */
 433  +       if (mbootinfo && (mbootinfo->flags & MBOOTINFO_HAVE_MEMMAP))
 434  +               E820_MAP_NR = mboot_2_e820_map(E820_MAP, E820_MAP_NR);
 435          sanitize_e820_map(E820_MAP, &E820_MAP_NR);
 436          if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
 437                  unsigned long mem_size;
 438
 439  +               if (mbootinfo) {
 440  +                       who = "Multiboot-Loader:";
 441  +                       e820.nr_map = 0;
 442  +                       add_memory_region(0, mbootinfo->mem_lower << 10, E820_RAM);
 443  +                       add_memory_region(HIGH_MEMORY, mbootinfo->mem_upper << 10, E820_RAM);
 444  +               } else {
 445                  /* compare results from other methods and take the greater */
 446                  if (ALT_MEM_K < EXT_MEM_K) {
 447                          mem_size = EXT_MEM_K;
 448  @@ -693,6 +730,7 @@
 449                  add_memory_region(0, LOWMEMSIZE(), E820_RAM);
 450                  add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
 451          }
 452  +       }
 453          printk(KERN_INFO "BIOS-provided physical RAM map:\n");
 454          print_memory_map(who);
 455   } /* setup_memory_region */
 456  @@ -704,8 +742,11 @@
 457          int len = 0;
 458          int usermem = 0;
 459
 460  +       if ((mbootinfo) && (mbootinfo->flags & MBOOTINFO_HAVE_CMDLINE))
 461  +               from = mbootinfo->cmdline;
 462  +
 463          /* Save unparsed command line copy for /proc/cmdline */
 464  -       memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 465  +       memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
 466          saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 467
 468          for (;;) {
 469  @@ -768,6 +809,86 @@
 470          }
 471   }
 472
 473  +#define INFBOUND(a,b)  if (b > a) a = b
 474  +#define SUPBOUND(a,b)  if (b < a) a = b
 475  +
 476  +
 477  +unsigned long get_bootmembitmap_addr(void)
 478  +{
 479  +       unsigned long start_pfn = __pa(&_end);
 480  +
 481  +#ifdef CONFIG_MODULES
 482  +
 483  +       if ((mbootinfo) && (mbootinfo->flags & MBOOTINFO_HAVE_MODULE)) {
 484  +               int i;
 485  +               struct multiboot_module *addr = mbootinfo->mods_addr;
 486  +
 487  +               mboot_module_start = 0xFFFFFFFF;
 488  +               mboot_module_end = 0;
 489  +
 490  +               for(i=0;i<mbootinfo->mods_count;i++) {
 491  +                       INFBOUND(start_pfn,addr[i].mod_end);
 492  +
 493  +                       addr[i].mod_start += __PAGE_OFFSET;
 494  +                       addr[i].mod_end += __PAGE_OFFSET;
 495  +
 496  +                       SUPBOUND(mboot_module_start,addr[i].mod_start);
 497  +                       INFBOUND(mboot_module_end,addr[i].mod_end);
 498  +
 499  +               }
 500  +               printk(KERN_INFO "Multiboot module mem 0x%lx - 0x%lx\n",mboot_module_start, mboot_module_end);
 501  +       }
 502  +
 503  +#endif
 504  +
 505  +       return start_pfn;
 506  +}
 507  +
 508  +#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 509  +#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
 510  +#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
 511  +
 512  +void reserve_mbootinfo_mem(void)
 513  +{
 514  +       if (mbootinfo) {
 515  +               mboot_mem_start = (unsigned long)mbootinfo;
 516  +               mboot_mem_end = (unsigned long)mbootinfo + sizeof(*mbootinfo);
 517  +
 518  +               if (mbootinfo->flags & MBOOTINFO_HAVE_MODULE) {
 519  +                       int i;
 520  +
 521  +                       SUPBOUND(mboot_mem_start,(unsigned long)mbootinfo->mods_addr);
 522  +                       INFBOUND(mboot_mem_end,(unsigned long)mbootinfo->mods_addr +
 523  +                               sizeof(struct multiboot_module) * mbootinfo->mods_count);
 524  +
 525  +                       for(i=0;i<mbootinfo->mods_count;i++) {
 526  +                               char *str;
 527  +                               struct multiboot_module *addr = &mbootinfo->mods_addr[i];
 528  +
 529  +                               SUPBOUND(mboot_mem_start,(unsigned long)addr->string);
 530  +                               for(str = addr->string;str[0] != 0;str++);
 531  +                               INFBOUND(mboot_mem_end,(unsigned long)str);
 532  +
 533  +                               (unsigned int)addr->string += __PAGE_OFFSET;
 534  +                       }
 535  +                       SUPBOUND(mboot_mem_start,(unsigned int)mbootinfo->mods_addr);
 536  +                       INFBOUND(mboot_mem_end,(unsigned int)mbootinfo->mods_addr);
 537  +                       (unsigned int)mbootinfo->mods_addr += __PAGE_OFFSET;
 538  +
 539  +               }
 540  +
 541  +               mboot_mem_start = PFN_PHYS(PFN_DOWN(mboot_mem_start));
 542  +               mboot_mem_end   = PFN_PHYS(PFN_UP(mboot_mem_end));
 543  +
 544  +               printk(KERN_NOTICE "Reserving Multiboot Memory 0x%lx - 0x%lx\n",mboot_mem_start,mboot_mem_end);
 545  +               reserve_bootmem(mboot_mem_start, mboot_mem_end - mboot_mem_start);
 546  +
 547  +               mboot_mem_start += __PAGE_OFFSET;
 548  +               mboot_mem_end += __PAGE_OFFSET;
 549  +               (unsigned int)mbootinfo += __PAGE_OFFSET;
 550  +       }
 551  +}
 552  +
 553   void __init setup_arch(char **cmdline_p)
 554   {
 555          unsigned long bootmap_size, low_mem_size;
 556  @@ -780,8 +901,27 @@
 557
 558          ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
 559          drive_info = DRIVE_INFO;
 560  +
 561  +       if (mbootinfo) {
 562  +
 563  +               screen_info.orig_x = 0;                 /* 0x00 */
 564  +               screen_info.orig_y = 0;                 /* 0x01 */
 565  +               screen_info.orig_video_page = 8;                /* 0x04 */
 566  +               screen_info.orig_video_mode = 3;                /* 0x06 */
 567  +               screen_info.orig_video_cols = 80;               /* 0x07 */
 568  +               screen_info.orig_video_ega_bx = 3;      /* 0x0a */
 569  +               screen_info.orig_video_lines = 25;      /* 0x0e */
 570  +               screen_info.orig_video_isVGA = 1;       /* 0x0f */
 571  +               screen_info.orig_video_points = 16;     /* 0x10 */
 572  +
 573  +               if (mbootinfo->flags & MBOOTINFO_HAVE_APMTABLE)
 574  +                       apm_info.bios = *mbootinfo->apm_table;
 575  +
 576  +       } else {
 577          screen_info = SCREEN_INFO;
 578          apm_info.bios = APM_BIOS_INFO;
 579  +       }
 580  +
 581          if( SYS_DESC_TABLE.length != 0 ) {
 582                  MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
 583                  machine_id = SYS_DESC_TABLE.table[0];
 584  @@ -811,10 +951,6 @@
 585
 586          parse_mem_cmdline(cmdline_p);
 587
 588  -#define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 589  -#define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
 590  -#define PFN_PHYS(x)    ((x) << PAGE_SHIFT)
 591  -
 592   /*
 593    * 128MB for vmalloc and initrd
 594    */
 595  @@ -827,7 +963,7 @@
 596           * partially used pages are not usable - thus
 597           * we are rounding upwards:
 598           */
 599  -       start_pfn = PFN_UP(__pa(&_end));
 600  +       start_pfn = PFN_UP(get_bootmembitmap_addr());
 601
 602          /*
 603           * Find the highest page frame number we have available
 604  @@ -941,6 +1077,8 @@
 605           */
 606          reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
 607   #endif
 608  +
 609  +       reserve_mbootinfo_mem();
 610
 611   #ifdef CONFIG_X86_LOCAL_APIC
 612          /*
 613  diff -urbN linux/arch/i386/mm/init.c linux.new/arch/i386/mm/init.c
 614  --- linux/arch/i386/mm/init.c   Fri Sep 21 04:59:20 2001
 615  +++ linux.new/arch/i386/mm/init.c       Wed Dec  5 23:59:33 2001
 616  @@ -36,6 +36,7 @@
 617   #include <asm/e820.h>
 618   #include <asm/apic.h>
 619   #include <asm/tlb.h>
 620  +#include <asm/multiboot.h>
 621
 622   mmu_gather_t mmu_gathers[NR_CPUS];
 623   unsigned long highstart_pfn, highend_pfn;
 624  @@ -541,18 +542,34 @@
 625          return flag;
 626   }
 627
 628  +#define FREE_RESERVED_MEM(addr) {\
 629  +       ClearPageReserved(virt_to_page(addr)); \
 630  +       set_page_count(virt_to_page(addr), 1); \
 631  +       free_page(addr); \
 632  +       totalram_pages++; \
 633  +}
 634  +
 635   void free_initmem(void)
 636   {
 637          unsigned long addr;
 638
 639  -       addr = (unsigned long)(&__init_begin);
 640  -       for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
 641  -               ClearPageReserved(virt_to_page(addr));
 642  -               set_page_count(virt_to_page(addr), 1);
 643  -               free_page(addr);
 644  -               totalram_pages++;
 645  +       if (mbootinfo) {
 646  +               for (addr = mboot_mem_start; addr < mboot_mem_end; addr += PAGE_SIZE)
 647  +                       FREE_RESERVED_MEM(addr);
 648  +               printk ("Freeing Multiboot memory: %ldk freed\n", (mboot_mem_end - mboot_mem_start) >> 10);
 649  +
 650  +               if ((mbootinfo->flags & MBOOTINFO_HAVE_MODULE) && (mbootinfo->mods_count > 0)) {
 651  +                       for (addr = mboot_module_start; addr < mboot_module_end; addr += PAGE_SIZE)
 652  +                               FREE_RESERVED_MEM(addr);
 653  +                       printk ("Freeing Multiboot-Module memory: %ldk freed\n", (mboot_module_end - mboot_module_start) >> 10);
 654  +               }
 655  +
 656          }
 657  +       addr = (unsigned long)(&__init_begin);
 658  +       for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE)
 659  +               FREE_RESERVED_MEM(addr);
 660          printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
 661  +
 662   }
 663
 664   #ifdef CONFIG_BLK_DEV_INITRD
 665  @@ -560,12 +577,8 @@
 666   {
 667          if (start < end)
 668                  printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 669  -       for (; start < end; start += PAGE_SIZE) {
 670  -               ClearPageReserved(virt_to_page(start));
 671  -               set_page_count(virt_to_page(start), 1);
 672  -               free_page(start);
 673  -               totalram_pages++;
 674  -       }
 675  +       for (; start < end; start += PAGE_SIZE)
 676  +               FREE_RESERVED_MEM(start);
 677   }
 678   #endif
 679
 680  diff -urbN linux/arch/i386/vmlinux.lds linux.new/arch/i386/vmlinux.lds
 681  --- linux/arch/i386/vmlinux.lds Mon Jul  2 23:40:14 2001
 682  +++ linux.new/arch/i386/vmlinux.lds     Wed Nov 28 00:11:57 2001
 683  @@ -3,33 +3,34 @@
 684    */
 685   OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 686   OUTPUT_ARCH(i386)
 687  -ENTRY(_start)
 688  +ENTRY(_lmabase)
 689   SECTIONS
 690   {
 691  +  _lmabase = multiboot_entry - 0xC0000000;
 692     . = 0xC0000000 + 0x100000;
 693     _text = .;                   /* Text and read-only data */
 694  -  .text : {
 695  +  .text : AT (ADDR(.text) - 0xC0000000) {
 696          *(.text)
 697          *(.fixup)
 698          *(.gnu.warning)
 699          } = 0x9090
 700  -  .text.lock : { *(.text.lock) }       /* out-of-line lock text */
 701  +  .text.lock : AT (ADDR(.text.lock) - 0xC0000000) { *(.text.lock) }    /* out-of-line lock text */
 702
 703     _etext = .;                  /* End of text section */
 704
 705  -  .rodata : { *(.rodata) *(.rodata.*) }
 706  -  .kstrtab : { *(.kstrtab) }
 707  +  .rodata : AT (ADDR(.rodata) - 0xC0000000) { *(.rodata) *(.rodata.*) }
 708  +  .kstrtab : AT (ADDR(.kstrtab) - 0xC0000000) { *(.kstrtab) }
 709
 710     . = ALIGN(16);               /* Exception table */
 711     __start___ex_table = .;
 712  -  __ex_table : { *(__ex_table) }
 713  +  __ex_table : AT (ADDR(__ex_table) - 0xC0000000) { *(__ex_table) }
 714     __stop___ex_table = .;
 715
 716     __start___ksymtab = .;       /* Kernel symbol table */
 717  -  __ksymtab : { *(__ksymtab) }
 718  +  __ksymtab : AT (ADDR(__ksymtab) - 0xC0000000) { *(__ksymtab) }
 719     __stop___ksymtab = .;
 720
 721  -  .data : {                    /* Data */
 722  +  .data : AT (ADDR(.data) - 0xC0000000) {                      /* Data */
 723          *(.data)
 724          CONSTRUCTORS
 725          }
 726  @@ -37,30 +38,30 @@
 727     _edata = .;                  /* End of data section */
 728
 729     . = ALIGN(8192);             /* init_task */
 730  -  .data.init_task : { *(.data.init_task) }
 731  +  .data.init_task : AT (ADDR(.data.init_task) - 0xC0000000) { *(.data.init_task) }
 732
 733     . = ALIGN(4096);             /* Init code and data */
 734     __init_begin = .;
 735  -  .text.init : { *(.text.init) }
 736  -  .data.init : { *(.data.init) }
 737  +  .text.init : AT (ADDR(.text.init) - 0xC0000000) { *(.text.init) }
 738  +  .data.init : AT (ADDR(.data.init) - 0xC0000000) { *(.data.init) }
 739     . = ALIGN(16);
 740     __setup_start = .;
 741  -  .setup.init : { *(.setup.init) }
 742  +  .setup.init : AT (ADDR(.setup.init) - 0xC0000000) { *(.setup.init) }
 743     __setup_end = .;
 744     __initcall_start = .;
 745  -  .initcall.init : { *(.initcall.init) }
 746  +  .initcall.init : AT (ADDR(.initcall.init) - 0xC0000000) { *(.initcall.init) }
 747     __initcall_end = .;
 748     . = ALIGN(4096);
 749     __init_end = .;
 750
 751     . = ALIGN(4096);
 752  -  .data.page_aligned : { *(.data.idt) }
 753  +  .data.page_aligned : AT (ADDR(.data.page_aligned) - 0xC0000000) { *(.data.idt) }
 754
 755     . = ALIGN(32);
 756  -  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
 757  +  .data.cacheline_aligned : AT (ADDR(.data.cacheline_aligned) - 0xC0000000) { *(.data.cacheline_aligned) }
 758
 759     __bss_start = .;             /* BSS */
 760  -  .bss : {
 761  +  .bss : AT (ADDR(.bss) - 0xC0000000) {
 762          *(.bss)
 763          }
 764     _end = . ;
 765  diff -urbN linux/include/asm-i386/multiboot.h linux.new/include/asm-i386/multiboot.h
 766  --- linux/include/asm-i386/multiboot.h  Thu Jan  1 01:00:00 1970
 767  +++ linux.new/include/asm-i386/multiboot.h      Thu Dec  6 17:39:44 2001
 768  @@ -0,0 +1,147 @@
 769  +/* multiboot.h - the header for Multiboot */
 770  +/* Copyright (C) 1999, 2001  Free Software Foundation, Inc.
 771  +   
 772  +   This program is free software; you can redistribute it and/or modify
 773  +   it under the terms of the GNU General Public License as published by
 774  +   the Free Software Foundation; either version 2 of the License, or
 775  +   (at your option) any later version.
 776  +   
 777  +   This program is distributed in the hope that it will be useful,
 778  +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 779  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 780  +   GNU General Public License for more details.
 781  +   
 782  +   You should have received a copy of the GNU General Public License
 783  +   aint with this program; if not, write to the Free Software
 784  +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 785  +
 786  +/* Macros.  */
 787  +
 788  +/* The magic number for the Multiboot header.  */
 789  +#define MULTIBOOT_HEADER_MAGIC         0x1BADB002
 790  +
 791  +/* The flags for the Multiboot header.  */
 792  +# define MULTIBOOT_HEADER_FLAGS                0x00000003
 793  +
 794  +/* The magic number passed by a Multiboot-compliant boot loader.  */
 795  +#define MULTIBOOT_BOOTLOADER_MAGIC     0x2BADB002
 796  +
 797  +/* The size of our stack (16KB).  */
 798  +#define STACK_SIZE                     0x4000
 799  +
 800  +/* C symbol format. HAVE_ASM_USCORE is defined by configure.  */
 801  +#ifdef HAVE_ASM_USCORE
 802  +# define EXT_C(sym)                    _ ## sym
 803  +#else
 804  +# define EXT_C(sym)                    sym
 805  +#endif
 806  +
 807  +#define MBOOTINFO_HAVE_MEMINFO         1
 808  +#define MBOOTINFO_HAVE_BOOTDEVICE      2
 809  +#define MBOOTINFO_HAVE_CMDLINE         4
 810  +#define MBOOTINFO_HAVE_MODULE          8
 811  +#define MBOOTINFO_HAVE_AOUTINFO                16
 812  +#define MBOOTINFO_HAVE_ELFINFO         32
 813  +#define MBOOTINFO_HAVE_MEMMAP          64
 814  +#define MBOOTINFO_HAVE_DRIVEINFO       128
 815  +#define MBOOTINFO_HAVE_ROMINFO         256
 816  +#define MBOOTINFO_HAVE_LOADERNAME      512
 817  +#define MBOOTINFO_HAVE_APMTABLE                1024
 818  +#define MBOOTINFO_HAVE_VIDEOINFO       2048
 819  +
 820  +#ifndef ASM
 821  +
 822  +#include <linux/apm_bios.h>
 823  +/* Do not include here in boot.S.  */
 824  +
 825  +extern struct multiboot_info *mbootinfo;
 826  +extern unsigned long mboot_mem_start;
 827  +extern unsigned long mboot_mem_end;
 828  +extern unsigned long mboot_module_start;
 829  +extern unsigned long mboot_module_end;
 830  +
 831  +/* Types.  */
 832  +
 833  +/* The Multiboot header.  */
 834  +struct multiboot_header
 835  +{
 836  +  unsigned int magic;
 837  +  unsigned int flags;
 838  +  unsigned int checksum;
 839  +  unsigned int header_addr;
 840  +  unsigned int load_addr;
 841  +  unsigned int load_end_addr;
 842  +  unsigned int bss_end_addr;
 843  +  unsigned int entry_addr;
 844  +};
 845  +
 846  +/* The symbol table for a.out.  */
 847  +struct multiboot_aout_symbol_table
 848  +{
 849  +  unsigned int tabsize;
 850  +  unsigned int strsize;
 851  +  unsigned int addr;
 852  +  unsigned int reserved;
 853  +};
 854  +
 855  +/* The section header table for ELF.  */
 856  +struct multiboot_elf_section_header_table
 857  +{
 858  +  unsigned int num;
 859  +  unsigned int size;
 860  +  unsigned int addr;
 861  +  unsigned int shndx;
 862  +};
 863  +
 864  +/* The module structure.  */
 865  +struct multiboot_module
 866  +{
 867  +  unsigned int mod_start;
 868  +  unsigned int mod_end;
 869  +  char *string;
 870  +  unsigned int reserved;
 871  +};
 872  +
 873  +/* The Multiboot information.  */
 874  +struct multiboot_info
 875  +{
 876  +  unsigned int flags;
 877  +  unsigned int mem_lower;
 878  +  unsigned int mem_upper;
 879  +  unsigned int boot_device;
 880  +  char *cmdline;
 881  +  unsigned int mods_count;
 882  +  struct multiboot_module *mods_addr;
 883  +  union
 884  +  {
 885  +    struct multiboot_aout_symbol_table aout_sym;
 886  +    struct multiboot_elf_section_header_table elf_sec;
 887  +  } u;
 888  +  unsigned int mmap_length;
 889  +  char *mmap_addr;
 890  +  unsigned int drives_length;
 891  +  unsigned int drives_addr;
 892  +  unsigned int config_table;
 893  +  char *boot_loader_name;
 894  +  struct apm_bios_info *apm_table;
 895  +  unsigned int vbe_control_info;
 896  +  unsigned int vbe_mode_info;
 897  +  unsigned short vbe_mode;
 898  +  unsigned short vbe_interface_seg;
 899  +  unsigned short vbe_interface_off;
 900  +  unsigned short vbe_interface_len;
 901  +};
 902  +
 903  +/* The memory map. Be careful that the offset 0 is base_addr_low
 904  +   but no size.  */
 905  +struct multiboot_memory_map
 906  +{
 907  +  unsigned int size;
 908  +  unsigned int base_addr_low;
 909  +  unsigned int base_addr_high;
 910  +  unsigned int length_low;
 911  +  unsigned int length_high;
 912  +  unsigned int  type;
 913  +};
 914  +
 915  +#endif /* ! ASM */
 916  diff -urbN linux/include/linux/obj_load.h linux.new/include/linux/obj_load.h
 917  --- linux/include/linux/obj_load.h      Thu Jan  1 01:00:00 1970
 918  +++ linux.new/include/linux/obj_load.h  Thu Dec  6 15:11:10 2001
 919  @@ -0,0 +1,297 @@
 920  +/* Elf object file loading and relocation routines.
 921  +   Copyright 1996, 1997 Linux International.
 922  +
 923  +   Contributed by Richard Henderson <rth@tamu.edu>
 924  +   obj_free() added by Björn Ekwall <bj0rn@blox.se> March 1999
 925  +
 926  +   This file is part of the Linux modutils.
 927  +
 928  +   This program is free software; you can redistribute it and/or modify it
 929  +   under the terms of the GNU General Public License as published by the
 930  +   Free Software Foundation; either version 2 of the License, or (at your
 931  +   option) any later version.
 932  +
 933  +   This program is distributed in the hope that it will be useful, but
 934  +   WITHOUT ANY WARRANTY; without even the implied warranty of
 935  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 936  +   General Public License for more details.
 937  +
 938  +   You should have received a copy of the GNU General Public License
 939  +   along with this program; if not, write to the Free Software Foundation,
 940  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 941  +
 942  +
 943  +#ifndef MODUTILS_OBJ_H
 944  +#define MODUTILS_OBJ_H 1
 945  +
 946  +#ident "$Id: obj.h 1.7 Tue, 02 Oct 2001 11:22:51 +1000 kaos $"
 947  +
 948  +/* The relocatable object is manipulated using elfin types.  */
 949  +
 950  +#include <linux/types.h>
 951  +#include <linux/elf.h>
 952  +
 953  +//#ifndef ElfW
 954  +//# if ELF_CLASS == ELFCLASS32
 955  +#  define ElfW(x)  Elf32_ ## x
 956  +#  define ELFW(x)  ELF32_ ## x
 957  +//# else
 958  +//#  define ElfW(x)  Elf64_ ## x
 959  +//#  define ELFW(x)  ELF64_ ## x
 960  +//# endif
 961  +//#endif
 962  +
 963  +#if defined(COMMON_3264) && defined(ONLY_32)
 964  +#  define ObjW(x)  obj32_ ## x
 965  +#else
 966  +#  if defined(COMMON_3264) && defined(ONLY_64)
 967  +#    define ObjW(x)  obj64_ ## x
 968  +#  else
 969  +#    define ObjW(x)    obj_ ## x
 970  +#  endif
 971  +#endif
 972  +
 973  +/* For some reason this is missing from lib5.  */
 974  +#ifndef ELF32_ST_INFO
 975  +# define ELF32_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
 976  +#endif
 977  +
 978  +#ifndef ELF64_ST_INFO
 979  +# define ELF64_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
 980  +#endif
 981  +
 982  +struct obj_string_patch_struct;
 983  +struct obj_symbol_patch_struct;
 984  +
 985  +struct obj_section
 986  +{
 987  +  ElfW(Shdr) header;
 988  +  const char *name;
 989  +  char *contents;
 990  +  struct obj_section *load_next;
 991  +  int idx;
 992  +};
 993  +
 994  +struct obj_symbol
 995  +{
 996  +  struct obj_symbol *next;     /* hash table link */
 997  +  const char *name;
 998  +  unsigned long value;
 999  +  unsigned long size;
1000  +  int secidx;                  /* the defining section index/module */
1001  +  int info;
1002  +  int ksymidx;                 /* for export to the kernel symtab */
1003  +  int r_type;                  /* relocation type */
1004  +};
1005  +
1006  +/* Hardcode the hash table size.  We shouldn't be needing so many
1007  +   symbols that we begin to degrade performance, and we get a big win
1008  +   by giving the compiler a constant divisor.  */
1009  +
1010  +#define HASH_BUCKETS  521
1011  +
1012  +struct obj_file
1013  +{
1014  +  ElfW(Ehdr) header;
1015  +  ElfW(Addr) baseaddr;
1016  +  struct obj_section **sections;
1017  +  struct obj_section *load_order;
1018  +  struct obj_section **load_order_search_start;
1019  +  struct obj_string_patch_struct *string_patches;
1020  +  struct obj_symbol_patch_struct *symbol_patches;
1021  +  int (*symbol_cmp)(const char *, const char *);
1022  +  unsigned long (*symbol_hash)(const char *);
1023  +  unsigned long local_symtab_size;
1024  +  struct obj_symbol **local_symtab;
1025  +  struct obj_symbol *symtab[HASH_BUCKETS];
1026  +  const char *filename;
1027  +  char *persist;
1028  +};
1029  +
1030  +enum obj_reloc
1031  +{
1032  +  obj_reloc_ok,
1033  +  obj_reloc_overflow,
1034  +  obj_reloc_dangerous,
1035  +  obj_reloc_unhandled,
1036  +  obj_reloc_constant_gp
1037  +};
1038  +
1039  +struct obj_string_patch_struct
1040  +{
1041  +  struct obj_string_patch_struct *next;
1042  +  int reloc_secidx;
1043  +  ElfW(Addr) reloc_offset;
1044  +  ElfW(Addr) string_offset;
1045  +};
1046  +
1047  +struct obj_symbol_patch_struct
1048  +{
1049  +  struct obj_symbol_patch_struct *next;
1050  +  int reloc_secidx;
1051  +  ElfW(Addr) reloc_offset;
1052  +  struct obj_symbol *sym;
1053  +};
1054  +
1055  +
1056  +/* Generic object manipulation routines.  */
1057  +
1058  +#define obj_elf_hash                   ObjW(elf_hash)
1059  +#define obj_elf_hash_n                 ObjW(elf_hash_n)
1060  +#define obj_add_symbol                 ObjW(add_symbol)
1061  +#define obj_find_symbol                        ObjW(find_symbol)
1062  +#define obj_symbol_final_value         ObjW(symbol_final_value)
1063  +#define obj_set_symbol_compare         ObjW(set_symbol_compare)
1064  +#define obj_find_section               ObjW(find_section)
1065  +#define obj_insert_section_load_order  ObjW(insert_section_load_order)
1066  +#define obj_create_alloced_section     ObjW(create_alloced_section)
1067  +#define obj_create_alloced_section_first \
1068  +                                       ObjW(create_alloced_section_first)
1069  +#define obj_extend_section             ObjW(extend_section)
1070  +#define obj_string_patch               ObjW(string_patch)
1071  +#define obj_symbol_patch               ObjW(symbol_patch)
1072  +#define obj_check_undefineds           ObjW(check_undefineds)
1073  +#define obj_clear_undefineds           ObjW(clear_undefineds)
1074  +#define obj_allocate_commons           ObjW(allocate_commons)
1075  +#define obj_load_size                  ObjW(load_size)
1076  +#define obj_relocate                   ObjW(relocate)
1077  +#define obj_load                       ObjW(load)
1078  +#define obj_free                       ObjW(free)
1079  +#define obj_create_image               ObjW(create_image)
1080  +#define obj_addr_to_native_ptr         ObjW(addr_to_native_ptr)
1081  +#define obj_native_ptr_to_addr         ObjW(native_ptr_to_addr)
1082  +#define obj_kallsyms                   ObjW(kallsyms)
1083  +#define arch_new_file                  ObjW(arch_new_file)
1084  +#define arch_new_section               ObjW(arch_new_section)
1085  +#define arch_new_symbol                        ObjW(arch_new_symbol)
1086  +#define arch_apply_relocation          ObjW(arch_apply_relocation)
1087  +#define arch_create_got                        ObjW(arch_create_got)
1088  +#define arch_init_module               ObjW(arch_init_module)
1089  +#define arch_load_proc_section         ObjW(arch_load_proc_section)
1090  +#define arch_finalize_section_address  ObjW(arch_finalize_section_address)
1091  +#define arch_archdata                  ObjW(arch_archdata)
1092  +
1093  +unsigned long obj_elf_hash (const char *);
1094  +
1095  +unsigned long obj_elf_hash_n (const char *, unsigned long len);
1096  +
1097  +struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
1098  +                                  unsigned long symidx, int info, int secidx,
1099  +                                  ElfW(Addr) value, unsigned long size);
1100  +
1101  +struct obj_symbol *obj_find_symbol (struct obj_file *f,
1102  +                                        const char *name);
1103  +
1104  +ElfW(Addr) obj_symbol_final_value (struct obj_file *f,
1105  +                                 struct obj_symbol *sym);
1106  +
1107  +void obj_set_symbol_compare (struct obj_file *f,
1108  +                           int (*cmp)(const char *, const char *),
1109  +                           unsigned long (*hash)(const char *));
1110  +
1111  +struct obj_section *obj_find_section (struct obj_file *f,
1112  +                                          const char *name);
1113  +
1114  +void obj_insert_section_load_order (struct obj_file *f,
1115  +                                   struct obj_section *sec);
1116  +
1117  +struct obj_section *obj_create_alloced_section (struct obj_file *f,
1118  +                                               const char *name,
1119  +                                               unsigned long align,
1120  +                                               unsigned long size,
1121  +                                               unsigned long flags);
1122  +
1123  +struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
1124  +                                                     const char *name,
1125  +                                                     unsigned long align,
1126  +                                                     unsigned long size);
1127  +
1128  +void *obj_extend_section (struct obj_section *sec, unsigned long more);
1129  +
1130  +int obj_string_patch (struct obj_file *f, int secidx, ElfW(Addr) offset,
1131  +                    const char *string);
1132  +
1133  +int obj_symbol_patch (struct obj_file *f, int secidx, ElfW(Addr) offset,
1134  +                    struct obj_symbol *sym);
1135  +
1136  +int obj_check_undefineds (struct obj_file *f, int quiet);
1137  +
1138  +void obj_clear_undefineds (struct obj_file *f);
1139  +
1140  +void obj_allocate_commons (struct obj_file *f);
1141  +
1142  +unsigned long obj_load_size (struct obj_file *f);
1143  +
1144  +int obj_relocate (struct obj_file *f, ElfW(Addr) base);
1145  +
1146  +struct obj_file *
1147  +obj_load (void *modmem, unsigned int modsize, Elf32_Half e_type, const char *filename);
1148  +
1149  +void obj_free (struct obj_file *f);
1150  +
1151  +int obj_create_image (struct obj_file *f, char *image);
1152  +
1153  +int obj_kallsyms (struct obj_file *fin, struct obj_file **fout);
1154  +
1155  +/* Architecture specific manipulation routines.  */
1156  +
1157  +struct obj_file *arch_new_file (void);
1158  +
1159  +struct obj_section *arch_new_section (void);
1160  +
1161  +struct obj_symbol *arch_new_symbol (void);
1162  +
1163  +enum obj_reloc arch_apply_relocation (struct obj_file *f,
1164  +                                     struct obj_section *targsec,
1165  +                                     struct obj_section *symsec,
1166  +                                     struct obj_symbol *sym,
1167  +                                     ElfW(Rel) *rel, ElfW(Addr) value);
1168  +
1169  +int arch_create_got (struct obj_file *f);
1170  +
1171  +struct module;
1172  +int arch_init_module (struct obj_file *f, struct module *);
1173  +
1174  +int arch_load_proc_section (struct obj_section *sec, int fp);
1175  +
1176  +int arch_finalize_section_address (struct obj_file *f, ElfW(Addr) base);
1177  +
1178  +int arch_archdata (struct obj_file *fin, struct obj_section *sec);
1179  +
1180  +#define ARCHDATA_SEC_NAME "__archdata"
1181  +
1182  +/* Pointers in objects can be 32 or 64 bit */
1183  +union obj_ptr_4 {
1184  +       Elf32_Word addr;
1185  +       void *ptr;
1186  +};
1187  +union obj_ptr_8 {
1188  +       u_int64_t addr; /* Should be Elf64_Xword but not all users have this yet */
1189  +       void *ptr;
1190  +};
1191  +
1192  +void *obj_addr_to_native_ptr(ElfW(Addr));
1193  +
1194  +ElfW(Addr) obj_native_ptr_to_addr(void *);
1195  +
1196  +/* Standard method of finding relocation symbols, sets isym */
1197  +#define obj_find_relsym(isym, f, find, rel, symtab, strtab) \
1198  +       { \
1199  +               unsigned long symndx = ELFW(R_SYM)((rel)->r_info); \
1200  +               ElfW(Sym) *extsym = (symtab)+symndx; \
1201  +               if (ELFW(ST_BIND)(extsym->st_info) == STB_LOCAL) { \
1202  +                       isym = (typeof(isym)) (f)->local_symtab[symndx]; \
1203  +               } \
1204  +               else { \
1205  +                       const char *name; \
1206  +                       if (extsym->st_name) \
1207  +                               name = (strtab) + extsym->st_name; \
1208  +                       else \
1209  +                               name = (f)->sections[extsym->st_shndx]->name; \
1210  +                       isym = (typeof(isym)) obj_find_symbol((find), name); \
1211  +               } \
1212  +       }
1213  +
1214  +int obj_gpl_license(struct obj_file *, const char **);
1215  +
1216  +#endif /* obj.h */
1217  diff -urbN linux/init/main.c linux.new/init/main.c
1218  --- linux/init/main.c   Fri Oct 12 19:17:15 2001
1219  +++ linux.new/init/main.c       Tue Dec  4 02:13:42 2001
1220  @@ -94,6 +94,7 @@
1221   extern void sysctl_init(void);
1222   extern void signals_init(void);
1223   extern int init_pcmcia_ds(void);
1224  +extern void init_boot_modules(void);
1225
1226   extern void free_initmem(void);
1227
1228  @@ -736,6 +737,7 @@
1229   #ifdef CONFIG_PCMCIA
1230          init_pcmcia_ds();               /* Do this last */
1231   #endif
1232  +       init_boot_modules();
1233   }
1234
1235   extern void rd_load(void);
1236  diff -urbN linux/kernel/Makefile linux.new/kernel/Makefile
1237  --- linux/kernel/Makefile       Mon Sep 17 06:22:40 2001
1238  +++ linux.new/kernel/Makefile   Wed Dec  5 22:28:24 2001
1239  @@ -14,7 +14,8 @@
1240   obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
1241              module.o exit.o itimer.o info.o time.o softirq.o resource.o \
1242              sysctl.o acct.o capability.o ptrace.o timer.o user.o \
1243  -           signal.o sys.o kmod.o context.o
1244  +           signal.o sys.o kmod.o context.o boot_modules.o \
1245  +           obj_common.o obj_reloc.o obj_gpl_license.o obj_load.o
1246
1247   obj-$(CONFIG_UID16) += uid16.o
1248   obj-$(CONFIG_MODULES) += ksyms.o
1249  diff -urbN linux/kernel/boot_modules.c linux.new/kernel/boot_modules.c
1250  --- linux/kernel/boot_modules.c Thu Jan  1 01:00:00 1970
1251  +++ linux.new/kernel/boot_modules.c     Thu Dec  6 15:11:02 2001
1252  @@ -0,0 +1,413 @@
1253  +/*
1254  + *  linux/kernel/boot_modules.c
1255  + *
1256  + *  Copyright (C) 2001 Christian König
1257  + *
1258  + *  Ervery thing here is GPL'ed.
1259  + */
1260  +
1261  +#include <linux/slab.h>
1262  +#include <linux/kernel.h>
1263  +
1264  +#ifndef __i386__ //this file should'n be arch dependent, but I'am lazy
1265  +
1266  +void init_boot_modules(void) {}
1267  +
1268  +#else
1269  +
1270  +#include <asm/multiboot.h>
1271  +#include <linux/obj_load.h>
1272  +#include <linux/version.h>
1273  +#include <linux/module.h>
1274  +
1275  +#define STRVERSIONLEN  32
1276  +
1277  +/*
1278  + * Conditionally add the symbols from the given symbol set
1279  + * to the new module.
1280  + */
1281  +static int add_symbols_from(struct obj_file *f, int idx,
1282  +                           struct module_symbol *syms, size_t nsyms, int gpl)
1283  +{
1284  +       struct module_symbol *s;
1285  +       size_t i;
1286  +       int used = 0;
1287  +
1288  +       for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1289  +               /*
1290  +                * Only add symbols that are already marked external.
1291  +                * If we override locals we may cause problems for
1292  +                * argument initialization.
1293  +                * We will also create a false dependency on the module.
1294  +                */
1295  +               struct obj_symbol *sym;
1296  +
1297  +               /* GPL licensed modules can use symbols exported with
1298  +                * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
1299  +                * exported names.  Non-GPL modules never see any GPLONLY_
1300  +                * symbols so they cannot fudge it by adding the prefix on
1301  +                * their references.
1302  +                */
1303  +               if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
1304  +                       if (gpl)
1305  +                               ((char *)s->name) += 8;
1306  +                       else
1307  +                               continue;
1308  +               }
1309  +
1310  +               sym = obj_find_symbol(f, (char *) s->name);
1311  +               if (sym && ELFW(ST_BIND) (sym->info) != STB_LOCAL) {
1312  +                       sym = obj_add_symbol(f, (char *) s->name, -1,
1313  +                                 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1314  +                                            idx, s->value, 0);
1315  +                       /*
1316  +                        * Did our symbol just get installed?
1317  +                        * If so, mark the module as "used".
1318  +                        */
1319  +                       if (sym->secidx == idx)
1320  +                               used = 1;
1321  +               }
1322  +       }
1323  +
1324  +       return used;
1325  +}
1326  +
1327  +static void add_kernel_symbols(struct obj_file *f, int gpl)
1328  +{
1329  +       struct module *mod;
1330  +       size_t i;
1331  +
1332  +       /* Add module symbols first.  */
1333  +       for (mod=module_list, i = 0; mod; mod=mod->next, i++)
1334  +               if (mod->nsyms)
1335  +                       add_symbols_from(f, SHN_HIRESERVE + 2 + i, mod->syms, mod->nsyms, gpl);
1336  +}
1337  +
1338  +static int create_this_module(struct obj_file *f, const char *m_name)
1339  +{
1340  +       struct obj_section *sec;
1341  +
1342  +       sec = obj_create_alloced_section_first(f, ".this", sizeof(long),
1343  +                                              sizeof(struct module));
1344  +       memset(sec->contents, 0, sizeof(struct module));
1345  +
1346  +       obj_add_symbol(f, "__this_module", -1, ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT),
1347  +                      sec->idx, 0, sizeof(struct module));
1348  +
1349  +       obj_string_patch(f, sec->idx, offsetof(struct module, name), m_name);
1350  +
1351  +       return 1;
1352  +}
1353  +
1354  +static void hide_special_symbols(struct obj_file *f)
1355  +{
1356  +       struct obj_symbol *sym;
1357  +       const char *const *p;
1358  +       static const char *const specials[] =
1359  +       {
1360  +               "cleanup_module",
1361  +               "init_module",
1362  +               "kernel_version",
1363  +               NULL
1364  +       };
1365  +
1366  +       for (p = specials; *p; ++p)
1367  +               if ((sym = obj_find_symbol(f, *p)) != NULL)
1368  +                       sym->info = ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
1369  +}
1370  +
1371  +static int create_module_ksymtab(struct obj_file *f)
1372  +{
1373  +       struct obj_section *sec;
1374  +       int i;
1375  +
1376  +       /* We must always add the module references.  */
1377  +
1378  +/*     if (n_ext_modules_used) {
1379  +               struct module_ref *dep;
1380  +               struct obj_symbol *tm;
1381  +
1382  +               sec = obj_create_alloced_section(f, ".kmodtab",
1383  +                       tgt_sizeof_void_p,
1384  +                       sizeof(struct module_ref) * n_ext_modules_used, 0);
1385  +               if (!sec)
1386  +                       return 0;
1387  +
1388  +               tm = obj_find_symbol(f, "__this_module");
1389  +               dep = (struct module_ref *) sec->contents;
1390  +               for (i = 0; i < n_module_stat; ++i)
1391  +                       if (module_stat[i].status ) {
1392  +                               dep->dep = module_stat[i].addr;
1393  +                               obj_symbol_patch(f, sec->idx, (char *) &dep->ref - sec->contents, tm);
1394  +                               dep->next_ref = 0;
1395  +                               ++dep;
1396  +                       }
1397  +       }*/
1398  +/*     if (!obj_find_section(f, "__ksymtab")) {
1399  +               int *loaded;
1400  +
1401  +                We don't want to export symbols residing in sections that
1402  +                  aren't loaded.  There are a number of these created so that
1403  +                  we make sure certain module options don't appear twice.
1404  +
1405  +               loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
1406  +               while (--i >= 0)
1407  +                       loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
1408  +
1409  +               for (i = 0; i < HASH_BUCKETS; ++i) {
1410  +                       struct obj_symbol *sym;
1411  +                       for (sym = f->symtab[i]; sym; sym = sym->next) {
1412  +                               if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1413  +                                   && sym->secidx <= SHN_HIRESERVE
1414  +                                   && (sym->secidx >= SHN_LORESERVE
1415  +                                       || loaded[sym->secidx])) {
1416  +                                       add_ksymtab(f, sym);
1417  +                               }
1418  +                       }
1419  +               }
1420  +       }*/
1421  +       return 1;
1422  +}
1423  +
1424  +extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
1425  +extern asmlinkage long sys_delete_module(const char *name_user);
1426  +extern asmlinkage long sys_init_module(const char *name_user, struct module *mod_user);
1427  +
1428  +static int init_module(const char *m_name, struct obj_file *f,
1429  +                      unsigned long m_size)
1430  +{
1431  +       struct module *module;
1432  +       struct obj_section *sec;
1433  +       void *image;
1434  +       int ret = 0;
1435  +       long m_addr;
1436  +
1437  +       sec = obj_find_section(f, ".this");
1438  +       module = (struct module *) sec->contents;
1439  +       m_addr = sec->header.sh_addr;
1440  +
1441  +       module->size_of_struct = sizeof(*module);
1442  +       module->size = m_size;
1443  +       module->flags = 0; //flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
1444  +
1445  +       sec = obj_find_section(f, "__ksymtab");
1446  +       if (sec && sec->header.sh_size) {
1447  +               module->syms = sec->header.sh_addr;
1448  +               module->nsyms = sec->header.sh_size / (2 * sizeof(char *));
1449  +       }
1450  +/*     if (n_ext_modules_used) {
1451  +               sec = obj_find_section(f, ".kmodtab");
1452  +               module->deps = sec->header.sh_addr;
1453  +               module->ndeps = n_ext_modules_used;
1454  +       }*/
1455  +       module->init = obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1456  +       module->cleanup = obj_symbol_final_value(f,
1457  +               obj_find_symbol(f, "cleanup_module"));
1458  +
1459  +       sec = obj_find_section(f, "__ex_table");
1460  +       if (sec) {
1461  +               module->ex_table_start = sec->header.sh_addr;
1462  +               module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
1463  +       }
1464  +       sec = obj_find_section(f, ".text.init");
1465  +       if (sec) {
1466  +               module->runsize = sec->header.sh_addr - m_addr;
1467  +       }
1468  +       sec = obj_find_section(f, ".data.init");
1469  +       if (sec) {
1470  +               if (!module->runsize ||
1471  +                   module->runsize > sec->header.sh_addr - m_addr)
1472  +                       module->runsize = sec->header.sh_addr - m_addr;
1473  +       }
1474  +/*     sec = obj_find_section(f, ARCHDATA_SEC_NAME);
1475  +       if (sec && sec->header.sh_size) {
1476  +               module->archdata_start = sec->header.sh_addr;
1477  +               module->archdata_end = module->archdata_start + sec->header.sh_size;
1478  +       }
1479  +       sec = obj_find_section(f, KALLSYMS_SEC_NAME);
1480  +       if (sec && sec->header.sh_size) {
1481  +               module->kallsyms_start = sec->header.sh_addr;
1482  +               module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
1483  +       }
1484  +       if (!arch_init_module(f, module))
1485  +               return 0;
1486  +*/
1487  +       /*
1488  +        * Whew!  All of the initialization is complete.
1489  +        * Collect the final module image and give it to the kernel.
1490  +        */
1491  +       image = kmalloc(m_size, GFP_KERNEL);
1492  +       obj_create_image(f, image);
1493  +
1494  +       if (ret == 0) {
1495  +//             fflush(stdout);         /* Flush any debugging output */
1496  +               ret = sys_init_module(m_name, (struct module *) image);
1497  +               if (ret) {
1498  +                       printk(KERN_INFO "init_module: %m\n");
1499  +                       printk(KERN_INFO "Hint: insmod errors can be caused by incorrect module parameters, "
1500  +                               "including invalid IO or IRQ parameters\n");
1501  +               }
1502  +       }
1503  +
1504  +       kfree(image);
1505  +
1506  +       return ret == 0;
1507  +}
1508  +
1509  +static int insert_module(struct obj_file *f, const char *m_name, int argc, char **argv)
1510  +{
1511  +       int gpl;
1512  +       unsigned long m_size;
1513  +       unsigned long m_addr;
1514  +
1515  +/*     int k_crcs;
1516  +       int m_version;
1517  +       char m_strversion[STRVERSIONLEN];
1518  +       int m_crcs;
1519  +
1520  +       m_version = get_module_version(f, m_strversion);
1521  +       if (m_version == -1) {
1522  +               printk(KERN_INFO "couldn't find the kernel version the module was compiled for");
1523  +               return 0;
1524  +       }
1525  +
1526  +       k_crcs = is_kernel_checksummed();
1527  +       m_crcs = is_module_checksummed(f);
1528  +       if ((m_crcs == 0 || k_crcs == 0) &&
1529  +           strncmp(m_strversion, UTS_RELEASE, STRVERSIONLEN) != 0) {
1530  +               printk(KERN_INFO "kernel-module version mismatch\n"
1531  +                     "\t%s was compiled for kernel version %s\n"
1532  +                     "\twhile this kernel is version %s.",
1533  +                     filename, m_strversion, UTS_RELEASE);
1534  +               return 0;
1535  +       }
1536  +       if (m_crcs != k_crcs)
1537  +               obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);*/
1538  +
1539  +       // We don't care about Versions for now
1540  +
1541  +       /* Let the module know about the kernel symbols.  */
1542  +       gpl = obj_gpl_license(f, NULL) == 0;
1543  +       add_kernel_symbols(f, gpl);
1544  +
1545  +       /* Allocate common symbols, symbol tables, and string tables.
1546  +        *
1547  +        * The calls marked DEPMOD indicate the bits of code that depmod
1548  +        * uses to do a pseudo relocation, ignoring undefined symbols.
1549  +        * Any changes made to the relocation sequence here should be
1550  +        * checked against depmod.
1551  +        */
1552  +       if (!create_this_module(f, m_name))
1553  +               return 0;
1554  +
1555  +       arch_create_got(f);     /* DEPMOD */
1556  +       if (!obj_check_undefineds(f, 0)) {      /* DEPMOD, obj_clear_undefineds */
1557  +               if (!gpl)
1558  +                       printk(KERN_INFO "Note: modules without a GPL compatible license cannot use GPLONLY_ symbols\n");
1559  +               return 0;
1560  +       }
1561  +       obj_allocate_commons(f);        /* DEPMOD */
1562  +
1563  +//     check_module_parameters(f, &persist_parms);
1564  +//     check_tainted_module(f, noload);
1565  +
1566  +/*     if (argc) {
1567  +               if (!process_module_arguments(f, argc, argv, 1))
1568  +                       return 0;
1569  +       }*/
1570  +       hide_special_symbols(f);
1571  +
1572  +/*     if (flag_ksymoops)
1573  +               add_ksymoops_symbols(f, filename, m_name);*/
1574  +
1575  +//     if (k_new_syscalls)
1576  +       create_module_ksymtab(f);
1577  +
1578  +       /* archdata based on relocatable addresses */
1579  +//     if (add_archdata(f, &archdata))
1580  +//             return 0;
1581  +
1582  +       /* kallsyms based on relocatable addresses */
1583  +//     if (add_kallsyms(f, &kallsyms, force_kallsyms))
1584  +//             return 0;
1585  +       /**** No symbols or sections to be changed after kallsyms above ***/
1586  +
1587  +//     if (errors)
1588  +//             return 0;
1589  +
1590  +       /* Module has now finished growing; find its size and install it.  */
1591  +       m_size = obj_load_size(f);      /* DEPMOD */
1592  +
1593  +//     errno = 0;
1594  +       m_addr = sys_create_module(m_name, m_size);
1595  +
1596  +       switch (-m_addr) {
1597  +       case 0:
1598  +               break;
1599  +       case EEXIST:
1600  +               printk(KERN_INFO "a module named %s already exists\n", m_name);
1601  +               return 0;
1602  +       case ENOMEM:
1603  +               printk(KERN_INFO "can't allocate kernel memory for module; needed %lu bytes\n",
1604  +                     m_size);
1605  +               return 0;
1606  +       default:
1607  +               if(m_addr > 127)
1608  +                       break;
1609  +               printk(KERN_INFO "create_module: %m\n");
1610  +               return 0;
1611  +       }
1612  +
1613  +       printk(KERN_INFO "Trying to relocate module @ 0x%x\n",m_addr);
1614  +       if (!obj_relocate(f, m_addr)) { /* DEPMOD */
1615  +               sys_delete_module(m_name);
1616  +               return 0;
1617  +       }
1618  +
1619  +       /* Do archdata again, this time we have the final addresses */
1620  +//     if (add_archdata(f, &archdata))
1621  +//             return 0;
1622  +
1623  +       /* Do kallsyms again, this time we have the final addresses */
1624  +//     if (add_kallsyms(f, &kallsyms, force_kallsyms))
1625  +//             return 0;
1626  +
1627  +       init_module(m_name, f, m_size);
1628  +/*     if (errors) {
1629  +               delete_module(m_name);
1630  +               return 0;
1631  +       }*/
1632  +       return 1;
1633  +}
1634  +
1635  +void init_boot_modules(void)
1636  +{
1637  +       int i;
1638  +       struct obj_file *f;
1639  +
1640  +       if(!mbootinfo)
1641  +               return;
1642  +       if(!(mbootinfo->flags & 8))
1643  +               return;
1644  +
1645  +       for(i=0;i<mbootinfo->mods_count;i++) {
1646  +               char *m_name;
1647  +               struct multiboot_module *mod = &mbootinfo->mods_addr[i];
1648  +
1649  +               for(m_name = mod->string;
1650  +                   (*m_name != 0) && (*m_name != ' ') && (strncmp(m_name,".o",2) != 0);
1651  +                   m_name++);
1652  +               *m_name = 0;
1653  +               for(;(m_name > mod->string) && (*m_name != '/');m_name--);
1654  +               m_name++;
1655  +
1656  +               printk(KERN_INFO "Ok Starting to load Module %s from addr 0x%x - 0x%x\n", m_name, mod->mod_start, mod->mod_end);
1657  +               f = obj_load ((void *)mod->mod_start, mod->mod_end - mod->mod_start, ET_REL, mod->string);
1658  +               if (!f) continue;
1659  +
1660  +               insert_module(f,m_name,0,0);
1661  +               obj_free(f);
1662  +       }
1663  +}
1664  +
1665  +#endif
1666  diff -urbN linux/kernel/obj_common.c linux.new/kernel/obj_common.c
1667  --- linux/kernel/obj_common.c   Thu Jan  1 01:00:00 1970
1668  +++ linux.new/kernel/obj_common.c       Wed Dec  5 23:24:38 2001
1669  @@ -0,0 +1,424 @@
1670  +/* Elf file, section, and symbol manipulation routines.
1671  +   Copyright 1996, 1997 Linux International.
1672  +
1673  +   Contributed by Richard Henderson <rth@tamu.edu>
1674  +
1675  +   This file is part of the Linux modutils.
1676  +
1677  +   This program is free software; you can redistribute it and/or modify it
1678  +   under the terms of the GNU General Public License as published by the
1679  +   Free Software Foundation; either version 2 of the License, or (at your
1680  +   option) any later version.
1681  +
1682  +   This program is distributed in the hope that it will be useful, but
1683  +   WITHOUT ANY WARRANTY; without even the implied warranty of
1684  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1685  +   General Public License for more details.
1686  +
1687  +   You should have received a copy of the GNU General Public License
1688  +   along with this program; if not, write to the Free Software Foundation,
1689  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1690  +
1691  +   Modified by Christian König (ChristianK.@t-online.de) to work inside the kernel*/
1692  +
1693  +#ident "$Id: obj_common.c 1.4 Wed, 26 Sep 2001 11:58:34 +1000 kaos $"
1694  +
1695  +#include <linux/slab.h>
1696  +
1697  +#include <linux/obj_load.h>
1698  +
1699  +/*======================================================================*/
1700  +
1701  +/* Standard ELF hash function.  */
1702  +inline unsigned long
1703  +obj_elf_hash_n(const char *name, unsigned long n)
1704  +{
1705  +  unsigned long h = 0;
1706  +  unsigned long g;
1707  +  unsigned char ch;
1708  +
1709  +  while (n > 0)
1710  +    {
1711  +      ch = *name++;
1712  +      h = (h << 4) + ch;
1713  +      if ((g = (h & 0xf0000000)) != 0)
1714  +       {
1715  +         h ^= g >> 24;
1716  +         h &= ~g;
1717  +       }
1718  +      n--;
1719  +    }
1720  +  return h;
1721  +}
1722  +
1723  +unsigned long
1724  +obj_elf_hash (const char *name)
1725  +{
1726  +  return obj_elf_hash_n(name, strlen(name));
1727  +}
1728  +
1729  +void
1730  +obj_set_symbol_compare (struct obj_file *f,
1731  +                       int (*cmp)(const char *, const char *),
1732  +                       unsigned long (*hash)(const char *))
1733  +{
1734  +  if (cmp)
1735  +    f->symbol_cmp = cmp;
1736  +  if (hash)
1737  +    {
1738  +      struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1739  +      int i;
1740  +
1741  +      f->symbol_hash = hash;
1742  +
1743  +      memcpy(tmptab, f->symtab, sizeof(tmptab));
1744  +      memset(f->symtab, 0, sizeof(f->symtab));
1745  +
1746  +      for (i = 0; i < HASH_BUCKETS; ++i)
1747  +       for (sym = tmptab[i]; sym ; sym = next)
1748  +         {
1749  +           unsigned long h = hash(sym->name) % HASH_BUCKETS;
1750  +           next = sym->next;
1751  +           sym->next = f->symtab[h];
1752  +           f->symtab[h] = sym;
1753  +         }
1754  +    }
1755  +}
1756  +
1757  +struct obj_symbol *
1758  +obj_add_symbol (struct obj_file *f, const char *name, unsigned long symidx,
1759  +               int info, int secidx, ElfW(Addr) value, unsigned long size)
1760  +{
1761  +  struct obj_symbol *sym;
1762  +  unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1763  +  int n_type = ELFW(ST_TYPE)(info);
1764  +  int n_binding = ELFW(ST_BIND)(info);
1765  +
1766  +  for (sym = f->symtab[hash]; sym; sym = sym->next)
1767  +    if (f->symbol_cmp(sym->name, name) == 0)
1768  +      {
1769  +       int o_secidx = sym->secidx;
1770  +       int o_info = sym->info;
1771  +       int o_type = ELFW(ST_TYPE)(o_info);
1772  +       int o_binding = ELFW(ST_BIND)(o_info);
1773  +
1774  +       /* A redefinition!  Is it legal?  */
1775  +
1776  +       if (secidx == SHN_UNDEF)
1777  +         return sym;
1778  +       else if (o_secidx == SHN_UNDEF)
1779  +         goto found;
1780  +       else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL)
1781  +         {
1782  +           /* Cope with local and global symbols of the same name
1783  +              in the same object file, as might have been created
1784  +              by ld -r.  The only reason locals are now seen at this
1785  +              level at all is so that we can do semi-sensible things
1786  +              with parameters.  */
1787  +
1788  +           struct obj_symbol *nsym, **p;
1789  +
1790  +           nsym = arch_new_symbol();
1791  +           nsym->next = sym->next;
1792  +           nsym->ksymidx = -1;
1793  +
1794  +           /* Excise the old (local) symbol from the hash chain.  */
1795  +           for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1796  +             continue;
1797  +           *p = sym = nsym;
1798  +           goto found;
1799  +         }
1800  +       else if (n_binding == STB_LOCAL)
1801  +         {
1802  +           /* Another symbol of the same name has already been defined.
1803  +              Just add this to the local table.  */
1804  +           sym = arch_new_symbol();
1805  +           sym->next = NULL;
1806  +           sym->ksymidx = -1;
1807  +           f->local_symtab[symidx] = sym;
1808  +           goto found;
1809  +         }
1810  +       else if (n_binding == STB_WEAK)
1811  +         return sym;
1812  +       else if (o_binding == STB_WEAK)
1813  +         goto found;
1814  +       /* Don't unify COMMON symbols with object types the programmer
1815  +          doesn't expect.  */
1816  +       else if (secidx == SHN_COMMON
1817  +                && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1818  +         return sym;
1819  +       else if (o_secidx == SHN_COMMON
1820  +                && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1821  +         goto found;
1822  +       else
1823  +         {
1824  +           /* Don't report an error if the symbol is coming from
1825  +              the kernel or some external module.  */
1826  +           if (secidx <= SHN_HIRESERVE)
1827  +             printk(KERN_INFO "%s multiply defined", name);
1828  +           return sym;
1829  +         }
1830  +      }
1831  +
1832  +  /* Completely new symbol.  */
1833  +  sym = arch_new_symbol();
1834  +  sym->next = f->symtab[hash];
1835  +  f->symtab[hash] = sym;
1836  +  sym->ksymidx = -1;
1837  +
1838  +  if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1839  +    if (symidx >= f->local_symtab_size)
1840  +      printk(KERN_INFO "local symbol %s with index %ld exceeds local_symtab_size %ld",
1841  +        name, (long) symidx, (long) f->local_symtab_size);
1842  +    else
1843  +      f->local_symtab[symidx] = sym;
1844  +  }
1845  +
1846  +found:
1847  +  sym->name = name;
1848  +  sym->value = value;
1849  +  sym->size = size;
1850  +  sym->secidx = secidx;
1851  +  sym->info = info;
1852  +  sym->r_type = 0;     /* should be R_arch_NONE for all arch */
1853  +
1854  +  return sym;
1855  +}
1856  +
1857  +struct obj_symbol *
1858  +obj_find_symbol (struct obj_file *f, const char *name)
1859  +{
1860  +  struct obj_symbol *sym;
1861  +  unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1862  +
1863  +  for (sym = f->symtab[hash]; sym; sym = sym->next)
1864  +    if (f->symbol_cmp(sym->name, name) == 0)
1865  +      return sym;
1866  +
1867  +  return NULL;
1868  +}
1869  +
1870  +ElfW(Addr)
1871  +obj_symbol_final_value (struct obj_file *f, struct obj_symbol *sym)
1872  +{
1873  +  if (sym)
1874  +    {
1875  +      if (sym->secidx >= SHN_LORESERVE)
1876  +       return sym->value;
1877  +
1878  +      return sym->value + f->sections[sym->secidx]->header.sh_addr;
1879  +    }
1880  +  else
1881  +    {
1882  +      /* As a special case, a NULL sym has value zero.  */
1883  +      return 0;
1884  +    }
1885  +}
1886  +
1887  +struct obj_section *
1888  +obj_find_section (struct obj_file *f, const char *name)
1889  +{
1890  +  int i, n = f->header.e_shnum;
1891  +
1892  +  for (i = 0; i < n; ++i)
1893  +    if (strcmp(f->sections[i]->name, name) == 0)
1894  +      return f->sections[i];
1895  +
1896  +  return NULL;
1897  +}
1898  +
1899  +#if defined (ARCH_alpha)
1900  +#define ARCH_SHF_SHORT SHF_ALPHA_GPREL
1901  +#elif defined (ARCH_ia64)
1902  +#define ARCH_SHF_SHORT SHF_IA_64_SHORT
1903  +#else
1904  +#define ARCH_SHF_SHORT 0
1905  +#endif
1906  +
1907  +static int
1908  +obj_load_order_prio(struct obj_section *a)
1909  +{
1910  +  unsigned long af, ac;
1911  +
1912  +  af = a->header.sh_flags;
1913  +
1914  +  ac = 0;
1915  +  if (a->name[0] != '.'
1916  +      || strlen(a->name) != 10
1917  +      || strcmp(a->name + 5, ".init"))
1918  +    ac |= 64;
1919  +  if (af & SHF_ALLOC) ac |= 32;
1920  +  if (af & SHF_EXECINSTR) ac |= 16;
1921  +  if (!(af & SHF_WRITE)) ac |= 8;
1922  +  if (a->header.sh_type != SHT_NOBITS) ac |= 4;
1923  +  /* Desired order is
1924  +               P S  AC & 7
1925  +       .data   1 0  4
1926  +       .got    1 1  3
1927  +       .sdata  1 1  1
1928  +       .sbss   0 1  1
1929  +       .bss    0 0  0  */
1930  +  if (strcmp (a->name, ".got") == 0) ac |= 2;
1931  +  if (af & ARCH_SHF_SHORT)
1932  +    ac = (ac & ~4) | 1;
1933  +
1934  +  return ac;
1935  +}
1936  +
1937  +void
1938  +obj_insert_section_load_order (struct obj_file *f, struct obj_section *sec)
1939  +{
1940  +  struct obj_section **p;
1941  +  int prio = obj_load_order_prio(sec);
1942  +  for (p = f->load_order_search_start; *p ; p = &(*p)->load_next)
1943  +    if (obj_load_order_prio(*p) < prio)
1944  +      break;
1945  +  sec->load_next = *p;
1946  +  *p = sec;
1947  +}
1948  +
1949  +static void *realloc(void *ptr, unsigned int size, unsigned int oldsize)
1950  +{
1951  +       void *new;
1952  +       new = kmalloc(size, GFP_KERNEL);
1953  +       memcpy(new, ptr, oldsize);
1954  +       kfree(ptr);
1955  +       return new;
1956  +}
1957  +
1958  +struct obj_section *
1959  +obj_create_alloced_section (struct obj_file *f, const char *name,
1960  +                           unsigned long align, unsigned long size,
1961  +                           unsigned long flags)
1962  +{
1963  +  int newidx = f->header.e_shnum++;
1964  +  struct obj_section *sec;
1965  +
1966  +  f->sections = realloc(f->sections, (newidx+1) * sizeof(sec), newidx * sizeof(sec));
1967  +  f->sections[newidx] = sec = arch_new_section();
1968  +
1969  +  memset(sec, 0, sizeof(*sec));
1970  +  sec->header.sh_type = SHT_PROGBITS;
1971  +  sec->header.sh_flags = flags | SHF_ALLOC;
1972  +  sec->header.sh_size = size;
1973  +  sec->header.sh_addralign = align;
1974  +  sec->name = name;
1975  +  sec->idx = newidx;
1976  +  if (size)
1977  +    sec->contents = kmalloc(size, GFP_KERNEL);
1978  +
1979  +  obj_insert_section_load_order(f, sec);
1980  +
1981  +  return sec;
1982  +}
1983  +
1984  +struct obj_section *
1985  +obj_create_alloced_section_first (struct obj_file *f, const char *name,
1986  +                                 unsigned long align, unsigned long size)
1987  +{
1988  +  int newidx = f->header.e_shnum++;
1989  +  struct obj_section *sec;
1990  +
1991  +  f->sections = realloc(f->sections, (newidx+1) * sizeof(sec), newidx * sizeof(sec));
1992  +  f->sections[newidx] = sec = arch_new_section();
1993  +
1994  +  memset(sec, 0, sizeof(*sec));
1995  +  sec->header.sh_type = SHT_PROGBITS;
1996  +  sec->header.sh_flags = SHF_WRITE|SHF_ALLOC;
1997  +  sec->header.sh_size = size;
1998  +  sec->header.sh_addralign = align;
1999  +  sec->name = name;
2000  +  sec->idx = newidx;
2001  +  if (size)
2002  +    sec->contents = kmalloc(size, GFP_KERNEL);
2003  +
2004  +  sec->load_next = f->load_order;
2005  +  f->load_order = sec;
2006  +  if (f->load_order_search_start == &f->load_order)
2007  +    f->load_order_search_start = &sec->load_next;
2008  +
2009  +  return sec;
2010  +}
2011  +
2012  +void *
2013  +obj_extend_section (struct obj_section *sec, unsigned long more)
2014  +{
2015  +  unsigned long oldsize = sec->header.sh_size;
2016  +  sec->contents = realloc(sec->contents, sec->header.sh_size += more, oldsize);
2017  +  return sec->contents + oldsize;
2018  +}
2019  +
2020  +/* Convert an object pointer (address) to a native pointer and vice versa.
2021  + * It gets interesting when the object has 64 bit pointers but modutils
2022  + * is running 32 bit.  This is nasty code but it stops the compiler giving
2023  + * spurious warning messages.  "I know what I am doing" ...
2024  + */
2025  +
2026  +void *
2027  +obj_addr_to_native_ptr (ElfW(Addr) addr)
2028  +{
2029  +       unsigned int convert = (sizeof(void *) << 8) + sizeof(addr);    /* to, from */
2030  +       union obj_ptr_4 p4;
2031  +       union obj_ptr_8 p8;
2032  +       switch (convert) {
2033  +       case 0x0404:
2034  +               p4.addr = addr;
2035  +               return(p4.ptr);
2036  +               break;
2037  +       case 0x0408:
2038  +               p4.addr = addr;
2039  +               if (p4.addr != addr) {
2040  +                       printk(KERN_INFO "obj_addr_to_native_ptr truncation %lx",
2041  +                               (unsigned long) addr);
2042  +                       return NULL;
2043  +               }
2044  +               return(p4.ptr);
2045  +               break;
2046  +       case 0x0804:
2047  +               p8.addr = addr;
2048  +               return(p8.ptr);
2049  +               break;
2050  +       case 0x0808:
2051  +               p8.addr = addr;
2052  +               return(p8.ptr);
2053  +               break;
2054  +       default:
2055  +               printk(KERN_INFO "obj_addr_to_native_ptr unknown conversion 0x%04x", convert);
2056  +               return NULL;
2057  +       }
2058  +}
2059  +
2060  +ElfW(Addr)
2061  +obj_native_ptr_to_addr (void *ptr)
2062  +{
2063  +       unsigned int convert = (sizeof(ElfW(Addr)) << 8) + sizeof(ptr); /* to, from */
2064  +       union obj_ptr_4 p4;
2065  +       union obj_ptr_8 p8;
2066  +       switch (convert) {
2067  +       case 0x0404:
2068  +               p4.ptr = ptr;
2069  +               return(p4.addr);
2070  +               break;
2071  +       case 0x0408:
2072  +               p8.ptr = ptr;
2073  +               p4.addr = p8.addr;
2074  +               if (p4.addr != p8.addr) {
2075  +                       printk(KERN_INFO "obj_native_ptr_to_addr truncation %x",
2076  +                               p8.addr);
2077  +                       return 0;
2078  +               }
2079  +               return(p4.addr);
2080  +               break;
2081  +       case 0x0804:
2082  +               p4.ptr = ptr;
2083  +               return(p4.addr);        /* compiler expands to 8 */
2084  +               break;
2085  +       case 0x0808:
2086  +               p8.ptr = ptr;
2087  +               return(p8.addr);
2088  +               break;
2089  +       default:
2090  +               printk(KERN_INFO "obj_native_ptr_to_addr unknown conversion 0x%04x", convert);
2091  +               return 0;
2092  +       }
2093  +}
2094  diff -urbN linux/kernel/obj_gpl_license.c linux.new/kernel/obj_gpl_license.c
2095  --- linux/kernel/obj_gpl_license.c      Thu Jan  1 01:00:00 1970
2096  +++ linux.new/kernel/obj_gpl_license.c  Wed Dec  5 23:24:47 2001
2097  @@ -0,0 +1,63 @@
2098  +/* Return the type of license for a module.  0 for GPL, 1 for no license, 2 for
2099  +   non-GPL.  The license parameter is set to the license string or NULL.
2100  +
2101  +   This file is part of the Linux modutils.
2102  +
2103  +   This program is free software; you can redistribute it and/or modify it
2104  +   under the terms of the GNU General Public License as published by the
2105  +   Free Software Foundation; either version 2 of the License, or (at your
2106  +   option) any later version.
2107  +
2108  +   This program is distributed in the hope that it will be useful, but
2109  +   WITHOUT ANY WARRANTY; without even the implied warranty of
2110  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2111  +   General Public License for more details.
2112  +
2113  +   You should have received a copy of the GNU General Public License
2114  +   along with this program; if not, write to the Free Software Foundation,
2115  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2116  +  */
2117  +
2118  +#include <linux/kernel.h>
2119  +#include <linux/stddef.h>
2120  +#include <linux/slab.h>
2121  +
2122  +#include <linux/obj_load.h>
2123  +
2124  +/* This list must match *exactly* the list of allowable licenses in
2125  + * linux/include/linux/module.h.  Checking for leading "GPL" will not
2126  + * work, somebody will use "GPL sucks, this is proprietary".
2127  + */
2128  +static const char *gpl_licenses[] = {
2129  +       "GPL",
2130  +       "GPL and additional rights",
2131  +       "Dual BSD/GPL",
2132  +       "Dual MPL/GPL",
2133  +};
2134  +
2135  +int obj_gpl_license(struct obj_file *f, const char **license)
2136  +{
2137  +       struct obj_section *sec;
2138  +       if ((sec = obj_find_section(f, ".modinfo"))) {
2139  +               const char *value, *ptr, *endptr;
2140  +               ptr = sec->contents;
2141  +               endptr = ptr + sec->header.sh_size;
2142  +               while (ptr < endptr) {
2143  +                       if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
2144  +                               int i;
2145  +                               if (license)
2146  +                                       *license = value+1;
2147  +                               for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
2148  +                                       if (strcmp(value+1, gpl_licenses[i]) == 0)
2149  +                                               return(0);
2150  +                               }
2151  +                               return(2);
2152  +                       }
2153  +                       if (strchr(ptr, '\0'))
2154  +                               ptr = strchr(ptr, '\0') + 1;
2155  +                       else
2156  +                               ptr = endptr;
2157  +               }
2158  +       }
2159  +       return(1);
2160  +}
2161  diff -urbN linux/kernel/obj_load.c linux.new/kernel/obj_load.c
2162  --- linux/kernel/obj_load.c     Thu Jan  1 01:00:00 1970
2163  +++ linux.new/kernel/obj_load.c Wed Dec  5 23:24:53 2001
2164  @@ -0,0 +1,366 @@
2165  +/* Elf file reader.
2166  +   Copyright 1996, 1997 Linux International.
2167  +
2168  +   Contributed by Richard Henderson <rth@tamu.edu>
2169  +   obj_free() added by Björn Ekwall <bj0rn@blox.se> March 1999
2170  +   Support for kallsyms Keith Owens <kaos@ocs.com.au> April 2000
2171  +
2172  +   This file is part of the Linux modutils.
2173  +
2174  +   This program is free software; you can redistribute it and/or modify it
2175  +   under the terms of the GNU General Public License as published by the
2176  +   Free Software Foundation; either version 2 of the License, or (at your
2177  +   option) any later version.
2178  +
2179  +   This program is distributed in the hope that it will be useful, but
2180  +   WITHOUT ANY WARRANTY; without even the implied warranty of
2181  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2182  +   General Public License for more details.
2183  +
2184  +   You should have received a copy of the GNU General Public License
2185  +   along with this program; if not, write to the Free Software Foundation,
2186  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2187  +
2188  +   Modified by Christian König (ChristianK.@t-online.de) to work inside the kernel*/
2189  +
2190  +#ident "$Id: obj_load.c 1.4 Wed, 26 Sep 2001 14:50:45 +1000 kaos $"
2191  +
2192  +#include <linux/kernel.h>
2193  +#include <linux/stddef.h>
2194  +#include <linux/slab.h>
2195  +
2196  +#include <linux/obj_load.h>
2197  +//#include "util.h"
2198  +
2199  +/*======================================================================*/
2200  +
2201  +int memcpy_chk(void *src, unsigned int size, int index, void *dst, int dstsize)
2202  +{
2203  +       if((size-index) < dstsize)
2204  +               return 0;
2205  +       memcpy(dst, src + index, dstsize);
2206  +       return dstsize;
2207  +}
2208  +
2209  +struct obj_file *
2210  +obj_load (void *modmem, unsigned int modsize, Elf32_Half e_type, const char *filename)
2211  +{
2212  +  struct obj_file *f;
2213  +  ElfW(Shdr) *section_headers;
2214  +  int shnum, i;
2215  +  char *shstrtab;
2216  +
2217  +  /* Read the file header.  */
2218  +
2219  +  f = arch_new_file();
2220  +  memset(f, 0, sizeof(*f));
2221  +  f->symbol_cmp = strcmp;
2222  +  f->symbol_hash = obj_elf_hash;
2223  +  f->load_order_search_start = &f->load_order;
2224  +
2225  +  if (memcpy_chk(modmem, modsize, 0, &f->header, sizeof(f->header)) != sizeof(f->header))
2226  +    {
2227  +      printk(KERN_INFO "cannot read ELF header from %s\n", filename);
2228  +      obj_free(f);
2229  +      return NULL;
2230  +    }
2231  +
2232  +  if (f->header.e_ident[EI_MAG0] != ELFMAG0
2233  +      || f->header.e_ident[EI_MAG1] != ELFMAG1
2234  +      || f->header.e_ident[EI_MAG2] != ELFMAG2
2235  +      || f->header.e_ident[EI_MAG3] != ELFMAG3)
2236  +    {
2237  +      printk(KERN_INFO "%s is not an ELF file\n", filename);
2238  +      obj_free(f);
2239  +      return NULL;
2240  +    }
2241  +  if (f->header.e_ident[EI_CLASS] != ELF_CLASS
2242  +      || f->header.e_ident[EI_DATA] != ELF_DATA
2243  +      || f->header.e_ident[EI_VERSION] != EV_CURRENT
2244  +      || f->header.e_machine != ELF_ARCH)
2245  +    {
2246  +      printk(KERN_INFO "ELF file %s not for this architecture\n", filename);
2247  +      obj_free(f);
2248  +      return NULL;
2249  +    }
2250  +  if (f->header.e_type != e_type && e_type != ET_NONE)
2251  +    {
2252  +      switch (e_type) {
2253  +      case ET_REL:
2254  +       printk(KERN_INFO "ELF file %s not a relocatable object\n", filename);
2255  +       break;
2256  +      case ET_EXEC:
2257  +       printk(KERN_INFO "ELF file %s not an executable object\n", filename);
2258  +       break;
2259  +      default:
2260  +       printk(KERN_INFO "ELF file %s has wrong type, expecting %d got %d\n",
2261  +               filename, e_type, f->header.e_type);
2262  +       break;
2263  +      }
2264  +      obj_free(f);
2265  +      return NULL;
2266  +    }
2267  +
2268  +  /* Read the section headers.  */
2269  +
2270  +  if (f->header.e_shentsize != sizeof(ElfW(Shdr)))
2271  +    {
2272  +      printk(KERN_INFO "section header size mismatch %s: %lu != %lu\n",
2273  +           filename,
2274  +           (unsigned long)f->header.e_shentsize,
2275  +           (unsigned long)sizeof(ElfW(Shdr)));
2276  +      obj_free(f);
2277  +      return NULL;
2278  +    }
2279  +
2280  +  shnum = f->header.e_shnum;
2281  +  f->sections = kmalloc(sizeof(struct obj_section *) * shnum, GFP_KERNEL);
2282  +  memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2283  +
2284  +  section_headers = kmalloc(sizeof(ElfW(Shdr)) * shnum, GFP_KERNEL);
2285  +  if (memcpy_chk(modmem, modsize, f->header.e_shoff, section_headers, sizeof(ElfW(Shdr))*shnum) != sizeof(ElfW(Shdr))*shnum)
2286  +    {
2287  +      printk(KERN_INFO "reading ELF section headers %s: %m\n", filename);
2288  +      obj_free(f);
2289  +      return NULL;
2290  +    }
2291  +
2292  +  /* Read the section data.  */
2293  +
2294  +  for (i = 0; i < shnum; ++i)
2295  +    {
2296  +      struct obj_section *sec;
2297  +
2298  +      f->sections[i] = sec = arch_new_section();
2299  +      memset(sec, 0, sizeof(*sec));
2300  +
2301  +      sec->header = section_headers[i];
2302  +      sec->idx = i;
2303  +
2304  +      switch (sec->header.sh_type)
2305  +       {
2306  +       case SHT_NULL:
2307  +       case SHT_NOTE:
2308  +       case SHT_NOBITS:
2309  +         /* ignore */
2310  +         break;
2311  +
2312  +       case SHT_PROGBITS:
2313  +       case SHT_SYMTAB:
2314  +       case SHT_STRTAB:
2315  +       case SHT_REL:
2316  +       case SHT_RELA:
2317  +         if (sec->header.sh_size > 0)
2318  +           {
2319  +             sec->contents = kmalloc(sec->header.sh_size, GFP_KERNEL);
2320  +             if (memcpy_chk(modmem, modsize, sec->header.sh_offset, sec->contents, sec->header.sh_size) != sec->header.sh_size)
2321  +               {
2322  +                 printk(KERN_INFO "reading ELF section data %s: %m\n", filename);
2323  +                 obj_free(f);
2324  +                 return NULL;
2325  +               }
2326  +           }
2327  +         else
2328  +           sec->contents = NULL;
2329  +         break;
2330  +
2331  +/*#if SHT_RELM == SHT_REL
2332  +       case SHT_RELA:
2333  +         if (sec->header.sh_size) {
2334  +           printk(KERN_INFO "RELA relocations not supported on this architecture %s", filename);
2335  +           obj_free(f);
2336  +           return NULL;
2337  +         }
2338  +         break;
2339  +#else
2340  +       case SHT_REL:
2341  +         if (sec->header.sh_size) {
2342  +           printk(KERN_INFO "REL relocations not supported on this architecture %s", filename);
2343  +           obj_free(f);
2344  +           return NULL;
2345  +         }
2346  +         break;
2347  +#endif*/
2348  +
2349  +       default:
2350  +/*       if (sec->header.sh_type >= SHT_LOPROC)
2351  +           {
2352  +             if (arch_load_proc_section(sec, fp) < 0)
2353  +               return NULL;
2354  +             break;
2355  +           }*/
2356  +
2357  +         printk(KERN_INFO "can't handle sections of type %ld %s %d\n",
2358  +               (long)sec->header.sh_type, filename,i);
2359  +         obj_free(f);
2360  +         return NULL;
2361  +       }
2362  +    }
2363  +
2364  +  /* Do what sort of interpretation as needed by each section.  */
2365  +
2366  +  shstrtab = f->sections[f->header.e_shstrndx]->contents;
2367  +
2368  +  for (i = 0; i < shnum; ++i)
2369  +    {
2370  +      struct obj_section *sec = f->sections[i];
2371  +      sec->name = shstrtab + sec->header.sh_name;
2372  +    }
2373  +
2374  +  for (i = 0; i < shnum; ++i)
2375  +    {
2376  +      struct obj_section *sec = f->sections[i];
2377  +
2378  +      /* .modinfo and .modstring should be contents only but gcc has no
2379  +       *  attribute for that.  The kernel may have marked these sections as
2380  +       *  ALLOC, ignore the allocate bit.
2381  +       */
2382  +      if (strcmp(sec->name, ".modinfo") == 0 ||
2383  +         strcmp(sec->name, ".modstring") == 0)
2384  +       sec->header.sh_flags &= ~SHF_ALLOC;
2385  +
2386  +      if (sec->header.sh_flags & SHF_ALLOC)
2387  +       obj_insert_section_load_order(f, sec);
2388  +
2389  +      switch (sec->header.sh_type)
2390  +       {
2391  +       case SHT_SYMTAB:
2392  +         {
2393  +           unsigned long nsym, j;
2394  +           char *strtab;
2395  +           ElfW(Sym) *sym;
2396  +
2397  +           if (sec->header.sh_entsize != sizeof(ElfW(Sym)))
2398  +             {
2399  +               printk(KERN_INFO "symbol size mismatch %s: %lu != %lu\n",
2400  +                     filename,
2401  +                     (unsigned long)sec->header.sh_entsize,
2402  +                     (unsigned long)sizeof(ElfW(Sym)));
2403  +               obj_free(f);
2404  +               return NULL;
2405  +             }
2406  +
2407  +           nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2408  +           strtab = f->sections[sec->header.sh_link]->contents;
2409  +           sym = (ElfW(Sym) *) sec->contents;
2410  +
2411  +           /* Allocate space for a table of local symbols.  */
2412  +           j = f->local_symtab_size = sec->header.sh_info;
2413  +           f->local_symtab = kmalloc(j *= sizeof(struct obj_symbol *), GFP_KERNEL);
2414  +           memset(f->local_symtab, 0, j);
2415  +
2416  +           /* Insert all symbols into the hash table.  */
2417  +           for (j = 1, ++sym; j < nsym; ++j, ++sym)
2418  +             {
2419  +               const char *name;
2420  +               if (sym->st_name)
2421  +                 name = strtab+sym->st_name;
2422  +               else
2423  +                 name = f->sections[sym->st_shndx]->name;
2424  +
2425  +               obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2426  +                              sym->st_value, sym->st_size);
2427  +
2428  +             }
2429  +         }
2430  +       break;
2431  +       }
2432  +    }
2433  +
2434  +  /* second pass to add relocation data to symbols */
2435  +  for (i = 0; i < shnum; ++i)
2436  +    {
2437  +      struct obj_section *sec = f->sections[i];
2438  +      switch (sec->header.sh_type)
2439  +       {
2440  +       case SHT_REL:
2441  +       case SHT_RELA:
2442  +         {
2443  +           unsigned long nrel, j, nsyms;
2444  +           ElfW(Rel) *rel;
2445  +           struct obj_section *symtab;
2446  +           char *strtab;
2447  +           if (sec->header.sh_entsize != sizeof(ElfW(Rel)))
2448  +             {
2449  +               printk(KERN_INFO "relocation entry size mismatch %s: %lu != %lu\n",
2450  +                     filename,
2451  +                     (unsigned long)sec->header.sh_entsize,
2452  +                     (unsigned long)sizeof(ElfW(Rel)));
2453  +               obj_free(f);
2454  +               return NULL;
2455  +             }
2456  +
2457  +           nrel = sec->header.sh_size / sizeof(ElfW(Rel));
2458  +           rel = (ElfW(Rel) *) sec->contents;
2459  +           symtab = f->sections[sec->header.sh_link];
2460  +           nsyms = symtab->header.sh_size / symtab->header.sh_entsize;
2461  +           strtab = f->sections[symtab->header.sh_link]->contents;
2462  +
2463  +           /* Save the relocate type in each symbol entry.  */
2464  +           for (j = 0; j < nrel; ++j, ++rel)
2465  +             {
2466  +               struct obj_symbol *intsym;
2467  +               unsigned long symndx;
2468  +               symndx = ELFW(R_SYM)(rel->r_info);
2469  +               if (symndx)
2470  +                 {
2471  +                   if (symndx >= nsyms)
2472  +                     {
2473  +                       printk(KERN_INFO "%s: Bad symbol index: %08lx >= %08lx\n",
2474  +                             filename, symndx, nsyms);
2475  +                       continue;
2476  +                     }
2477  +
2478  +                   obj_find_relsym(intsym, f, f, rel, (ElfW(Sym) *)(symtab->contents), strtab);
2479  +                   intsym->r_type = ELFW(R_TYPE)(rel->r_info);
2480  +                 }
2481  +             }
2482  +         }
2483  +         break;
2484  +       }
2485  +    }
2486  +
2487  +  f->filename = kmalloc(strlen(filename), GFP_KERNEL);
2488  +  strcpy((char *)f->filename,filename);
2489  +
2490  +  return f;
2491  +}
2492  +
2493  +void obj_free(struct obj_file *f)
2494  +{
2495  +       struct obj_section *sec;
2496  +       struct obj_symbol *sym;
2497  +       struct obj_symbol *next;
2498  +       int i;
2499  +       int n;
2500  +
2501  +       if (f->sections) {
2502  +               n = f->header.e_shnum;
2503  +               for (i = 0; i < n; ++i) {
2504  +                       if ((sec = f->sections[i]) != NULL) {
2505  +                               if (sec->contents)
2506  +                                       kfree(sec->contents);
2507  +                               kfree(sec);
2508  +                       }
2509  +               }
2510  +               kfree(f->sections);
2511  +       }
2512  +
2513  +       for (i = 0; i < HASH_BUCKETS; ++i) {
2514  +               for (sym = f->symtab[i]; sym; sym = next) {
2515  +                       next = sym->next;
2516  +                       kfree(sym);
2517  +               }
2518  +       }
2519  +
2520  +       if (f->local_symtab)
2521  +               kfree(f->local_symtab);
2522  +
2523  +       if (f->filename)
2524  +               kfree((char *)(f->filename));
2525  +
2526  +       if (f->persist)
2527  +               kfree((char *)(f->persist));
2528  +
2529  +       kfree(f);
2530  +}
2531  diff -urbN linux/kernel/obj_reloc.c linux.new/kernel/obj_reloc.c
2532  --- linux/kernel/obj_reloc.c    Thu Jan  1 01:00:00 1970
2533  +++ linux.new/kernel/obj_reloc.c        Wed Dec  5 23:24:59 2001
2534  @@ -0,0 +1,423 @@
2535  +/* Elf relocation routines.
2536  +   Copyright 1996, 1997 Linux International.
2537  +
2538  +   Contributed by Richard Henderson <rth@tamu.edu>
2539  +
2540  +   This file is part of the Linux modutils.
2541  +
2542  +   This program is free software; you can redistribute it and/or modify it
2543  +   under the terms of the GNU General Public License as published by the
2544  +   Free Software Foundation; either version 2 of the License, or (at your
2545  +   option) any later version.
2546  +
2547  +   This program is distributed in the hope that it will be useful, but
2548  +   WITHOUT ANY WARRANTY; without even the implied warranty of
2549  +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2550  +   General Public License for more details.
2551  +
2552  +   You should have received a copy of the GNU General Public License
2553  +   along with this program; if not, write to the Free Software Foundation,
2554  +   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2555  +
2556  +#ident "$Id: obj_reloc.c 1.4 Wed, 26 Sep 2001 14:50:45 +1000 kaos $"
2557  +
2558  +#include <linux/kernel.h>
2559  +#include <linux/stddef.h>
2560  +#include <linux/slab.h>
2561  +
2562  +#include <linux/obj_load.h>
2563  +
2564  +/*======================================================================*/
2565  +
2566  +int
2567  +obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2568  +                const char *string)
2569  +{
2570  +  struct obj_string_patch_struct *p;
2571  +  struct obj_section *strsec;
2572  +  size_t len = strlen(string)+1;
2573  +  char *loc;
2574  +
2575  +  p = kmalloc(sizeof(*p), GFP_KERNEL);
2576  +  p->next = f->string_patches;
2577  +  p->reloc_secidx = secidx;
2578  +  p->reloc_offset = offset;
2579  +  f->string_patches = p;
2580  +
2581  +  strsec = obj_find_section(f, ".kstrtab");
2582  +  if (strsec == NULL)
2583  +    {
2584  +      strsec = obj_create_alloced_section(f, ".kstrtab", 1, len, 0);
2585  +      p->string_offset = 0;
2586  +      loc = strsec->contents;
2587  +    }
2588  +  else
2589  +    {
2590  +      p->string_offset = strsec->header.sh_size;
2591  +      loc = obj_extend_section(strsec, len);
2592  +    }
2593  +  memcpy(loc, string, len);
2594  +
2595  +  return 1;
2596  +}
2597  +
2598  +int
2599  +obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2600  +                struct obj_symbol *sym)
2601  +{
2602  +  struct obj_symbol_patch_struct *p;
2603  +
2604  +  p = kmalloc(sizeof(*p), GFP_KERNEL);
2605  +  p->next = f->symbol_patches;
2606  +  p->reloc_secidx = secidx;
2607  +  p->reloc_offset = offset;
2608  +  p->sym = sym;
2609  +  f->symbol_patches = p;
2610  +
2611  +  return 1;
2612  +}
2613  +
2614  +int
2615  +obj_check_undefineds(struct obj_file *f, int quiet)
2616  +{
2617  +  unsigned long i;
2618  +  int ret = 1;
2619  +
2620  +  for (i = 0; i < HASH_BUCKETS; ++i)
2621  +    {
2622  +      struct obj_symbol *sym;
2623  +      for (sym = f->symtab[i]; sym ; sym = sym->next)
2624  +       if (sym->secidx == SHN_UNDEF)
2625  +         {
2626  +           if (ELFW(ST_BIND)(sym->info) == STB_WEAK)
2627  +             {
2628  +               sym->secidx = SHN_ABS;
2629  +               sym->value = 0;
2630  +             }
2631  +           else if (sym->r_type) /* assumes R_arch_NONE is 0 on all arch */
2632  +             {
2633  +               if (!quiet)
2634  +                       printk(KERN_INFO "unresolved symbol %s", sym->name);
2635  +               ret = 0;
2636  +             }
2637  +         }
2638  +    }
2639  +
2640  +  return ret;
2641  +}
2642  +
2643  +void
2644  +obj_clear_undefineds(struct obj_file *f)
2645  +{
2646  +  unsigned long i;
2647  +  struct obj_symbol *sym;
2648  +  for (i = 0; i < HASH_BUCKETS; ++i)
2649  +    {
2650  +      for (sym = f->symtab[i]; sym ; sym = sym->next)
2651  +       if (sym->secidx == SHN_UNDEF)
2652  +         {
2653  +           sym->secidx = SHN_ABS;
2654  +           sym->value = 0;
2655  +         }
2656  +    }
2657  +}
2658  +
2659  +static void *realloc(void *ptr, unsigned int size, unsigned int oldsize)
2660  +{
2661  +       void *new;
2662  +       new = kmalloc(size, GFP_KERNEL);
2663  +       memcpy(new, ptr, oldsize);
2664  +       kfree(ptr);
2665  +       return new;
2666  +}
2667  +
2668  +void
2669  +obj_allocate_commons(struct obj_file *f)
2670  +{
2671  +  struct common_entry
2672  +  {
2673  +    struct common_entry *next;
2674  +    struct obj_symbol *sym;
2675  +  } *common_head = NULL;
2676  +
2677  +  unsigned long i;
2678  +
2679  +  for (i = 0; i < HASH_BUCKETS; ++i)
2680  +    {
2681  +      struct obj_symbol *sym;
2682  +      for (sym = f->symtab[i]; sym ; sym = sym->next)
2683  +       if (sym->secidx == SHN_COMMON)
2684  +         {
2685  +           /* Collect all COMMON symbols and sort them by size so as to
2686  +              minimize space wasted by alignment requirements.  */
2687  +           {
2688  +             struct common_entry **p, *n;
2689  +             for (p = &common_head; *p ; p = &(*p)->next)
2690  +               if (sym->size <= (*p)->sym->size)
2691  +                 break;
2692  +
2693  +             n = alloca(sizeof(*n));
2694  +             n->next = *p;
2695  +             n->sym = sym;
2696  +             *p = n;
2697  +           }
2698  +         }
2699  +    }
2700  +
2701  +  for (i = 1; i < f->local_symtab_size; ++i)
2702  +    {
2703  +      struct obj_symbol *sym = f->local_symtab[i];
2704  +      if (sym && sym->secidx == SHN_COMMON)
2705  +       {
2706  +         struct common_entry **p, *n;
2707  +         for (p = &common_head; *p ; p = &(*p)->next)
2708  +           if (sym == (*p)->sym)
2709  +             break;
2710  +           else if (sym->size < (*p)->sym->size)
2711  +             {
2712  +               n = alloca(sizeof(*n));
2713  +               n->next = *p;
2714  +               n->sym = sym;
2715  +               *p = n;
2716  +               break;
2717  +             }
2718  +       }
2719  +    }
2720  +
2721  +  if (common_head)
2722  +    {
2723  +      /* Find the bss section.  */
2724  +      for (i = 0; i < f->header.e_shnum; ++i)
2725  +       if (f->sections[i]->header.sh_type == SHT_NOBITS)
2726  +         break;
2727  +
2728  +      /* If for some reason there hadn't been one, create one.  */
2729  +      if (i == f->header.e_shnum)
2730  +       {
2731  +         struct obj_section *sec;
2732  +
2733  +         f->sections = realloc(f->sections, (i+1) * sizeof(sec), i * sizeof(sec));
2734  +         f->sections[i] = sec = arch_new_section();
2735  +         f->header.e_shnum = i+1;
2736  +
2737  +         memset(sec, 0, sizeof(*sec));
2738  +         sec->header.sh_type = SHT_PROGBITS;
2739  +         sec->header.sh_flags = SHF_WRITE|SHF_ALLOC;
2740  +         sec->name = ".bss";
2741  +         sec->idx = i;
2742  +       }
2743  +
2744  +      /* Allocate the COMMONS.  */
2745  +      {
2746  +       ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2747  +       ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2748  +       struct common_entry *c;
2749  +
2750  +       for (c = common_head; c ; c = c->next)
2751  +         {
2752  +           ElfW(Addr) align = c->sym->value;
2753  +
2754  +           if (align > max_align)
2755  +             max_align = align;
2756  +           if (bss_size & (align - 1))
2757  +             bss_size = (bss_size | (align - 1)) + 1;
2758  +
2759  +           c->sym->secidx = i;
2760  +           c->sym->value = bss_size;
2761  +
2762  +           bss_size += c->sym->size;
2763  +         }
2764  +
2765  +       f->sections[i]->header.sh_size = bss_size;
2766  +       f->sections[i]->header.sh_addralign = max_align;
2767  +      }
2768  +    }
2769  +
2770  +  /* For the sake of patch relocation and parameter initialization,
2771  +     allocate zeroed data for NOBITS sections now.  Note that after
2772  +     this we cannot assume NOBITS are really empty.  */
2773  +  for (i = 0; i < f->header.e_shnum; ++i)
2774  +    {
2775  +      struct obj_section *s = f->sections[i];
2776  +      if (s->header.sh_type == SHT_NOBITS)
2777  +       {
2778  +         if (s->header.sh_size)
2779  +           s->contents = memset(kmalloc(s->header.sh_size, GFP_KERNEL),
2780  +                                0, s->header.sh_size);
2781  +         else
2782  +           s->contents = NULL;
2783  +         s->header.sh_type = SHT_PROGBITS;
2784  +       }
2785  +    }
2786  +}
2787  +
2788  +unsigned long
2789  +obj_load_size (struct obj_file *f)
2790  +{
2791  +  unsigned long dot = 0;
2792  +  struct obj_section *sec;
2793  +
2794  +  /* Finalize the positions of the sections relative to one another.  */
2795  +
2796  +  for (sec = f->load_order; sec ; sec = sec->load_next)
2797  +    {
2798  +      ElfW(Addr) align;
2799  +
2800  +      align = sec->header.sh_addralign;
2801  +      if (align && (dot & (align - 1)))
2802  +       dot = (dot | (align - 1)) + 1;
2803  +
2804  +      sec->header.sh_addr = dot;
2805  +      dot += sec->header.sh_size;
2806  +    }
2807  +
2808  +  return dot;
2809  +}
2810  +
2811  +int
2812  +obj_relocate (struct obj_file *f, ElfW(Addr) base)
2813  +{
2814  +  int i, n = f->header.e_shnum;
2815  +  int ret = 1;
2816  +
2817  +  /* Finalize the addresses of the sections.  */
2818  +
2819  +  arch_finalize_section_address(f, base);
2820  +
2821  +  /* And iterate over all of the relocations.  */
2822  +
2823  +  for (i = 0; i < n; ++i)
2824  +    {
2825  +      struct obj_section *relsec, *symsec, *targsec, *strsec;
2826  +      ElfW(Rel) *rel, *relend;
2827  +      ElfW(Sym) *symtab;
2828  +      const char *strtab;
2829  +      unsigned long nsyms;
2830  +
2831  +      relsec = f->sections[i];
2832  +      if (relsec->header.sh_type != SHT_REL)
2833  +       continue;
2834  +
2835  +      symsec = f->sections[relsec->header.sh_link];
2836  +      targsec = f->sections[relsec->header.sh_info];
2837  +      strsec = f->sections[symsec->header.sh_link];
2838  +
2839  +      if (!(targsec->header.sh_flags & SHF_ALLOC))
2840  +       continue;
2841  +
2842  +      rel = (ElfW(Rel) *)relsec->contents;
2843  +      relend = rel + (relsec->header.sh_size / sizeof(ElfW(Rel)));
2844  +      symtab = (ElfW(Sym) *)symsec->contents;
2845  +      nsyms = symsec->header.sh_size / symsec->header.sh_entsize;
2846  +      strtab = (const char *)strsec->contents;
2847  +
2848  +      for (; rel < relend; ++rel)
2849  +       {
2850  +         ElfW(Addr) value = 0;
2851  +         struct obj_symbol *intsym = NULL;
2852  +         unsigned long symndx;
2853  +         const char *errmsg;
2854  +
2855  +         /* Attempt to find a value to use for this relocation.  */
2856  +
2857  +         symndx = ELFW(R_SYM)(rel->r_info);
2858  +         if (symndx)
2859  +           {
2860  +             /* Note we've already checked for undefined symbols.  */
2861  +
2862  +             if (symndx >= nsyms)
2863  +               {
2864  +                 printk(KERN_INFO "Bad symbol index: %08lx >= %08lx",
2865  +                       symndx, nsyms);
2866  +                 continue;
2867  +               }
2868  +
2869  +             obj_find_relsym(intsym, f, f, rel, symtab, strtab);
2870  +             value = obj_symbol_final_value(f, intsym);
2871  +           }
2872  +
2873  +#if SHT_RELM == SHT_RELA
2874  +         value += rel->r_addend;
2875  +#endif
2876  +
2877  +         /* Do it! */
2878  +         switch (arch_apply_relocation(f,targsec,symsec,intsym,rel,value))
2879  +           {
2880  +           case obj_reloc_ok:
2881  +             break;
2882  +
2883  +           case obj_reloc_overflow:
2884  +             errmsg = "Relocation overflow";
2885  +             goto bad_reloc;
2886  +           case obj_reloc_dangerous:
2887  +             errmsg = "Dangerous relocation";
2888  +             goto bad_reloc;
2889  +           case obj_reloc_unhandled:
2890  +             errmsg = "Unhandled relocation";
2891  +             goto bad_reloc;
2892  +           case obj_reloc_constant_gp:
2893  +             errmsg = "Modules compiled with -mconstant-gp cannot be loaded";
2894  +             goto bad_reloc;
2895  +           bad_reloc:
2896  +             printk(KERN_INFO "%s of type %ld for %s", errmsg,
2897  +                   (long)ELFW(R_TYPE)(rel->r_info), intsym->name);
2898  +             ret = 0;
2899  +             break;
2900  +           }
2901  +       }
2902  +    }
2903  +
2904  +  /* Finally, take care of the patches.  */
2905  +
2906  +  if (f->string_patches)
2907  +    {
2908  +      struct obj_string_patch_struct *p;
2909  +      struct obj_section *strsec;
2910  +      ElfW(Addr) strsec_base;
2911  +      strsec = obj_find_section(f, ".kstrtab");
2912  +      strsec_base = strsec->header.sh_addr;
2913  +
2914  +      for (p = f->string_patches; p ; p = p->next)
2915  +       {
2916  +         struct obj_section *targsec = f->sections[p->reloc_secidx];
2917  +         *(ElfW(Addr) *)(targsec->contents + p->reloc_offset)
2918  +           = strsec_base + p->string_offset;
2919  +       }
2920  +    }
2921  +
2922  +  if (f->symbol_patches)
2923  +    {
2924  +      struct obj_symbol_patch_struct *p;
2925  +
2926  +      for (p = f->symbol_patches; p; p = p->next)
2927  +       {
2928  +         struct obj_section *targsec = f->sections[p->reloc_secidx];
2929  +         *(ElfW(Addr) *)(targsec->contents + p->reloc_offset)
2930  +           = obj_symbol_final_value(f, p->sym);
2931  +       }
2932  +    }
2933  +
2934  +  return ret;
2935  +}
2936  +
2937  +int
2938  +obj_create_image (struct obj_file *f, char *image)
2939  +{
2940  +  struct obj_section *sec;
2941  +  ElfW(Addr) base = f->baseaddr;
2942  +
2943  +  for (sec = f->load_order; sec ; sec = sec->load_next)
2944  +    {
2945  +      char *secimg;
2946  +
2947  +      if (sec->contents == 0)
2948  +       continue;
2949  +
2950  +      secimg = image + (sec->header.sh_addr - base);
2951  +
2952  +      /* Note that we allocated data for NOBITS sections earlier.  */
2953  +      memcpy(secimg, sec->contents, sec->header.sh_size);
2954  +    }
2955  +
2956  +  return 1;
2957  +}