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 +}
|