2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Distributed under the terms of the NewOS License.
6 #include <kernel/kernel.h>
7 #include <sys/errors.h>
8 #include <kernel/elf.h>
9 #include <kernel/vfs.h>
10 #include <kernel/vm.h>
11 #include <kernel/thread.h>
12 #include <kernel/debug.h>
13 #include <kernel/heap.h>
14 #include <kernel/arch/cpu.h>
16 #include <sys/elf32.h>
18 #include <libc/string.h>
19 #include <libc/printf.h>
28 struct elf_image_info
{
29 struct elf_image_info
*next
;
33 struct elf_region regions
[2]; // describes the text and data regions
34 addr dynamic_ptr
; // pointer to the dynamic section
35 struct elf_linked_image
*linked_images
;
37 struct Elf32_Ehdr
*eheader
;
39 // pointer to symbol participation data structures
41 unsigned int *symhash
;
42 struct Elf32_Sym
*syms
;
44 struct Elf32_Rel
*rel
;
46 struct Elf32_Rela
*rela
;
48 struct Elf32_Rel
*pltrel
;
52 // XXX TK this shall contain a list of linked images
53 // (don't know enough about ELF how to get this list)
54 typedef struct elf_linked_image
{
55 struct elf_linked_image
*next
;
56 struct elf_image_info
*image
;
59 static struct elf_image_info
*kernel_images
= NULL
;
60 static struct elf_image_info
*kernel_image
= NULL
;
61 static mutex image_lock
;
62 static mutex image_load_lock
;
63 static image_id next_image_id
= 0;
65 #define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
66 #define SYMNAME(image, sym) STRING(image, (sym)->st_name)
67 #define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num])
68 #define HASHTABSIZE(image) ((image)->symhash[0])
69 #define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2])
70 #define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
72 static void insert_image_in_list(struct elf_image_info
*image
)
74 mutex_lock(&image_lock
);
76 image
->next
= kernel_images
;
77 kernel_images
= image
;
79 mutex_unlock(&image_lock
);
82 static void remove_image_from_list(struct elf_image_info
*image
)
84 struct elf_image_info
**ptr
;
86 mutex_lock(&image_lock
);
88 for(ptr
= &kernel_images
; *ptr
; ptr
= &(*ptr
)->next
) {
96 mutex_unlock(&image_lock
);
99 static struct elf_image_info
*find_image(image_id id
)
101 struct elf_image_info
*image
;
103 mutex_lock(&image_lock
);
105 for(image
= kernel_images
; image
; image
= image
->next
) {
109 mutex_unlock(&image_lock
);
114 static struct elf_image_info
*find_image_by_vnode(void *vnode
)
116 struct elf_image_info
*image
;
118 mutex_lock(&image_lock
);
120 for(image
= kernel_images
; image
; image
= image
->next
) {
121 if(image
->vnode
== vnode
)
124 mutex_unlock(&image_lock
);
129 static struct elf_image_info
*create_image_struct()
131 struct elf_image_info
*image
;
133 image
= kmalloc(sizeof(struct elf_image_info
));
136 memset(image
, 0, sizeof(struct elf_image_info
));
137 image
->regions
[0].id
= -1;
138 image
->regions
[1].id
= -1;
139 image
->id
= atomic_add(&next_image_id
, 1);
140 image
->ref_count
= 1;
141 image
->linked_images
= NULL
;
145 static unsigned long elf_hash(const unsigned char *name
)
147 unsigned long hash
= 0;
151 hash
= (hash
<< 4) + *name
++;
152 if((temp
= hash
& 0xf0000000))
159 static void dump_image_info(struct elf_image_info
*image
)
163 dprintf("elf_image_info at 0x%x:\n", image
);
164 dprintf(" next 0x%x\n", image
->next
);
165 dprintf(" id 0x%x\n", image
->id
);
167 dprintf(" regions[%d].id 0x%x\n", i
, image
->regions
[i
].id
);
168 dprintf(" regions[%d].start 0x%x\n", i
, image
->regions
[i
].start
);
169 dprintf(" regions[%d].size 0x%x\n", i
, image
->regions
[i
].size
);
170 dprintf(" regions[%d].delta %d\n", i
, image
->regions
[i
].delta
);
172 dprintf(" dynamic_ptr 0x%x\n", image
->dynamic_ptr
);
173 dprintf(" needed 0x%x\n", image
->needed
);
174 dprintf(" symhash 0x%x\n", image
->symhash
);
175 dprintf(" syms 0x%x\n", image
->syms
);
176 dprintf(" strtab 0x%x\n", image
->strtab
);
177 dprintf(" rel 0x%x\n", image
->rel
);
178 dprintf(" rel_len 0x%x\n", image
->rel_len
);
179 dprintf(" rela 0x%x\n", image
->rela
);
180 dprintf(" rela_len 0x%x\n", image
->rela_len
);
183 static void dump_symbol(struct elf_image_info
*image
, struct Elf32_Sym
*sym
)
186 dprintf("symbol at 0x%x, in image 0x%x\n", sym
, image
);
188 dprintf(" name index %d, '%s'\n", sym
->st_name
, SYMNAME(image
, sym
));
189 dprintf(" st_value 0x%x\n", sym
->st_value
);
190 dprintf(" st_size %d\n", sym
->st_size
);
191 dprintf(" st_info 0x%x\n", sym
->st_info
);
192 dprintf(" st_other 0x%x\n", sym
->st_other
);
193 dprintf(" st_shndx %d\n", sym
->st_shndx
);
196 static struct Elf32_Sym
*elf_find_symbol(struct elf_image_info
*image
, const char *name
)
201 if(!image
->dynamic_ptr
)
204 hash
= elf_hash(name
) % HASHTABSIZE(image
);
205 for(i
= HASHBUCKETS(image
)[hash
]; i
!= STN_UNDEF
; i
= HASHCHAINS(image
)[i
]) {
206 if(!strcmp(SYMNAME(image
, &image
->syms
[i
]), name
)) {
207 return &image
->syms
[i
];
214 addr
elf_lookup_symbol(image_id id
, const char *symbol
)
216 struct elf_image_info
*image
;
217 struct Elf32_Sym
*sym
;
219 //dprintf( "elf_lookup_symbol: %s\n", symbol );
221 image
= find_image(id
);
225 sym
= elf_find_symbol(image
, symbol
);
229 if(sym
->st_shndx
== SHN_UNDEF
) {
233 /*dprintf( "found: %x (%x + %x)\n", sym->st_value + image->regions[0].delta,
234 sym->st_value, image->regions[0].delta );*/
235 return sym
->st_value
+ image
->regions
[0].delta
;
238 static int elf_parse_dynamic_section(struct elf_image_info
*image
)
242 int needed_offset
= -1;
244 // dprintf("top of elf_parse_dynamic_section\n");
250 d
= (struct Elf32_Dyn
*)image
->dynamic_ptr
;
254 for(i
=0; d
[i
].d_tag
!= DT_NULL
; i
++) {
257 needed_offset
= d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
;
260 image
->symhash
= (unsigned int *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
263 image
->strtab
= (char *)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
266 image
->syms
= (struct Elf32_Sym
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
269 image
->rel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
272 image
->rel_len
= d
[i
].d_un
.d_val
;
275 image
->rela
= (struct Elf32_Rela
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
278 image
->rela_len
= d
[i
].d_un
.d_val
;
280 // TK: procedure linkage table
282 image
->pltrel
= (struct Elf32_Rel
*)(d
[i
].d_un
.d_ptr
+ image
->regions
[0].delta
);
285 image
->pltrel_len
= d
[i
].d_un
.d_val
;
292 // lets make sure we found all the required sections
293 if(!image
->symhash
|| !image
->syms
|| !image
->strtab
)
296 // dprintf("needed_offset = %d\n", needed_offset);
298 if(needed_offset
>= 0)
299 image
->needed
= STRING(image
, needed_offset
);
304 // this function first tries to see if the first image and it's already resolved symbol is okay, otherwise
305 // it tries to link against the shared_image
306 // XXX gross hack and needs to be done better
307 static int elf_resolve_symbol(struct elf_image_info
*image
, struct Elf32_Sym
*sym
, struct elf_image_info
*shared_image
, const char *sym_prepend
,addr
*sym_addr
)
309 struct Elf32_Sym
*sym2
;
310 char new_symname
[512];
312 switch(sym
->st_shndx
) {
314 // patch the symbol name
315 strcpy(new_symname
, sym_prepend
);
316 strcat(new_symname
, SYMNAME(image
, sym
));
318 // it's undefined, must be outside this image, try the other image
319 sym2
= elf_find_symbol(shared_image
, new_symname
);
321 dprintf("elf_resolve_symbol: could not resolve symbol '%s'\n", new_symname
);
322 return ERR_ELF_RESOLVING_SYMBOL
;
325 // make sure they're the same type
326 if(ELF32_ST_TYPE(sym
->st_info
) != ELF32_ST_TYPE(sym2
->st_info
)) {
327 dprintf("elf_resolve_symbol: found symbol '%s' in shared image but wrong type\n", new_symname
);
328 return ERR_ELF_RESOLVING_SYMBOL
;
331 if(ELF32_ST_BIND(sym2
->st_info
) != STB_GLOBAL
&& ELF32_ST_BIND(sym2
->st_info
) != STB_WEAK
) {
332 dprintf("elf_resolve_symbol: found symbol '%s' but not exported\n", new_symname
);
333 return ERR_ELF_RESOLVING_SYMBOL
;
336 *sym_addr
= sym2
->st_value
+ shared_image
->regions
[0].delta
;
339 *sym_addr
= sym
->st_value
;
343 dprintf("elf_resolve_symbol: COMMON symbol, finish me!\n");
344 return ERR_NOT_IMPLEMENTED_YET
;
347 *sym_addr
= sym
->st_value
+ image
->regions
[0].delta
;
352 static int elf_relocate_rel(struct elf_image_info
*image
, const char *sym_prepend
,
353 struct Elf32_Rel
*rel
, int rel_len
)
356 struct Elf32_Sym
*sym
;
365 for(i
= 0; i
* (int)sizeof(struct Elf32_Rel
) < rel_len
; i
++) {
366 //dprintf("looking at rel type %d, offset 0x%x\n", ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset);
369 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
375 sym
= SYMBOL(image
, ELF32_R_SYM(rel
[i
].r_info
));
377 vlErr
= elf_resolve_symbol(image
, sym
, kernel_image
, sym_prepend
,&S
);
378 if(vlErr
<0) return vlErr
;
379 //dprintf("S 0x%x\n", S);
382 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
390 A
= *(addr
*)(image
->regions
[0].delta
+ rel
[i
].r_offset
);
391 // dprintf("A 0x%x\n", A);
395 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
400 P
= image
->regions
[0].delta
+ rel
[i
].r_offset
;
401 // dprintf("P 0x%x\n", P);
405 switch(ELF32_R_TYPE(rel
[i
].r_info
)) {
412 final_val
= S
+ A
- P
;
416 final_val
= image
->regions
[0].delta
+ A
;
420 dprintf( "final=%x\n", final_val
);
423 dprintf("unhandled relocation type %d\n", ELF32_R_TYPE(rel
[i
].r_info
));
424 return ERR_NOT_ALLOWED
;
426 *(addr
*)(image
->regions
[0].delta
+ rel
[i
].r_offset
) = final_val
;
432 // XXX for now just link against the kernel
433 static int elf_relocate(struct elf_image_info
*image
, const char *sym_prepend
)
437 // dprintf("top of elf_relocate\n");
439 // deal with the rels first
441 //dprintf( "total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel) );
442 res
= elf_relocate_rel( image
, sym_prepend
, image
->rel
, image
->rel_len
);
448 if( image
->pltrel
) {
449 //dprintf( "total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel) );
450 res
= elf_relocate_rel( image
, sym_prepend
, image
->pltrel
, image
->pltrel_len
);
457 dprintf("RELA relocations not supported\n");
458 return ERR_NOT_ALLOWED
;
459 for(i
= 1; i
* (int)sizeof(struct Elf32_Rela
) < image
->rela_len
; i
++) {
460 dprintf("rela: type %d\n", ELF32_R_TYPE(image
->rela
[i
].r_info
));
466 static int verify_eheader(struct Elf32_Ehdr
*eheader
)
468 if(memcmp(eheader
->e_ident
, ELF_MAGIC
, 4) != 0)
469 return ERR_INVALID_BINARY
;
471 if(eheader
->e_ident
[4] != ELFCLASS32
)
472 return ERR_INVALID_BINARY
;
474 if(eheader
->e_phoff
== 0)
475 return ERR_INVALID_BINARY
;
477 if(eheader
->e_phentsize
< sizeof(struct Elf32_Phdr
))
478 return ERR_INVALID_BINARY
;
483 int elf_load_uspace(const char *path
, struct proc
*p
, int flags
, addr
*entry
)
485 struct Elf32_Ehdr eheader
;
486 struct Elf32_Phdr
*pheaders
= NULL
;
492 dprintf("elf_load: entry path '%s', proc 0x%x\n", path
, p
);
494 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
498 len
= sys_read(fd
, &eheader
, 0, sizeof(eheader
));
503 if(len
!= sizeof(eheader
)) {
505 err
= ERR_INVALID_BINARY
;
508 err
= verify_eheader(&eheader
);
512 pheaders
= kmalloc(eheader
.e_phnum
* eheader
.e_phentsize
);
513 if(pheaders
== NULL
) {
514 dprintf("error allocating space for program headers\n");
519 dprintf("reading in program headers at 0x%x, len 0x%x\n", eheader
.e_phoff
, eheader
.e_phnum
* eheader
.e_phentsize
);
520 len
= sys_read(fd
, pheaders
, eheader
.e_phoff
, eheader
.e_phnum
* eheader
.e_phentsize
);
523 dprintf("error reading in program headers\n");
526 if(len
!= eheader
.e_phnum
* eheader
.e_phentsize
) {
527 dprintf("short read while reading in program headers\n");
532 for(i
=0; i
< eheader
.e_phnum
; i
++) {
533 char region_name
[64];
537 sprintf(region_name
, "%s_seg%d", path
, i
);
539 region_addr
= (char *)ROUNDOWN(pheaders
[i
].p_vaddr
, PAGE_SIZE
);
540 id
= vm_create_anonymous_region(p
->aspace_id
, region_name
, (void **)®ion_addr
, REGION_ADDR_EXACT_ADDRESS
,
541 ROUNDUP(pheaders
[i
].p_memsz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
), REGION_WIRING_LAZY
, LOCK_RW
);
543 dprintf("error allocating region!\n");
544 err
= ERR_INVALID_BINARY
;
548 len
= sys_read(fd
, region_addr
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), pheaders
[i
].p_offset
, pheaders
[i
].p_filesz
);
551 dprintf("error reading in seg %d\n", i
);
556 dprintf("elf_load: done!\n");
558 *entry
= eheader
.e_entry
;
570 image_id
elf_load_kspace(const char *path
, const char *sym_prepend
)
572 struct Elf32_Ehdr
*eheader
;
573 struct Elf32_Phdr
*pheaders
;
574 struct elf_image_info
*image
;
581 dprintf("elf_load_kspace: entry path '%s'\n", path
);
583 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
587 err
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
591 // XXX awful hack to keep someone else from trying to load this image
592 // probably not a bad thing, shouldn't be too many races
593 mutex_lock(&image_load_lock
);
595 // make sure it's not loaded already. Search by vnode
596 image
= find_image_by_vnode(vnode
);
598 atomic_add( &image
->ref_count
, 1 );
599 //err = ERR_NOT_ALLOWED;
603 eheader
= (struct Elf32_Ehdr
*)kmalloc( sizeof( *eheader
));
609 len
= sys_read(fd
, eheader
, 0, sizeof(*eheader
));
614 if(len
!= sizeof(*eheader
)) {
616 err
= ERR_INVALID_BINARY
;
619 err
= verify_eheader(eheader
);
623 image
= create_image_struct();
628 image
->vnode
= vnode
;
629 image
->eheader
= eheader
;
631 pheaders
= kmalloc(eheader
->e_phnum
* eheader
->e_phentsize
);
632 if(pheaders
== NULL
) {
633 dprintf("error allocating space for program headers\n");
638 // dprintf("reading in program headers at 0x%x, len 0x%x\n", eheader.e_phoff, eheader.e_phnum * eheader.e_phentsize);
639 len
= sys_read(fd
, pheaders
, eheader
->e_phoff
, eheader
->e_phnum
* eheader
->e_phentsize
);
642 dprintf("error reading in program headers\n");
645 if(len
!= eheader
->e_phnum
* eheader
->e_phentsize
) {
646 dprintf("short read while reading in program headers\n");
651 for(i
=0; i
< eheader
->e_phnum
; i
++) {
652 char region_name
[64];
653 bool ro_segment_handled
= false;
654 bool rw_segment_handled
= false;
658 // dprintf("looking at program header %d\n", i);
660 switch(pheaders
[i
].p_type
) {
664 image
->dynamic_ptr
= pheaders
[i
].p_vaddr
;
667 dprintf("unhandled pheader type 0x%x\n", pheaders
[i
].p_type
);
671 // we're here, so it must be a PT_LOAD segment
672 if((pheaders
[i
].p_flags
& (PF_R
| PF_W
| PF_X
)) == (PF_R
| PF_W
)) {
673 // this is the writable segment
674 if(rw_segment_handled
) {
675 // we've already created this segment
678 rw_segment_handled
= true;
680 lock
= LOCK_RW
|LOCK_KERNEL
;
681 sprintf(region_name
, "%s_rw", path
);
682 } else if((pheaders
[i
].p_flags
& (PF_R
| PF_W
| PF_X
)) == (PF_R
| PF_X
)) {
683 // this is the non-writable segment
684 if(ro_segment_handled
) {
685 // we've already created this segment
688 ro_segment_handled
= true;
690 // lock = LOCK_RO|LOCK_KERNEL;
691 lock
= LOCK_RW
|LOCK_KERNEL
;
692 sprintf(region_name
, "%s_ro", path
);
694 dprintf("weird program header flags 0x%x\n", pheaders
[i
].p_flags
);
697 image
->regions
[image_region
].size
= ROUNDUP(pheaders
[i
].p_memsz
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
), PAGE_SIZE
);
698 image
->regions
[image_region
].id
= vm_create_anonymous_region(vm_get_kernel_aspace_id(), region_name
,
699 (void **)&image
->regions
[image_region
].start
, REGION_ADDR_ANY_ADDRESS
,
700 image
->regions
[image_region
].size
, REGION_WIRING_WIRED
, lock
);
701 if(image
->regions
[image_region
].id
< 0) {
702 dprintf("error allocating region!\n");
703 err
= ERR_INVALID_BINARY
;
706 image
->regions
[image_region
].delta
= image
->regions
[image_region
].start
- ROUNDOWN(pheaders
[i
].p_vaddr
, PAGE_SIZE
);
708 // dprintf("elf_load_kspace: created a region at 0x%x\n", image->regions[image_region].start);
710 len
= sys_read(fd
, (void *)(image
->regions
[image_region
].start
+ (pheaders
[i
].p_vaddr
% PAGE_SIZE
)),
711 pheaders
[i
].p_offset
, pheaders
[i
].p_filesz
);
714 dprintf("error reading in seg %d\n", i
);
719 if(image
->regions
[1].start
!= 0) {
720 if(image
->regions
[0].delta
!= image
->regions
[1].delta
) {
721 dprintf("could not load binary, fix the region problem!\n");
722 dump_image_info(image
);
728 // modify the dynamic ptr by the delta of the regions
729 image
->dynamic_ptr
+= image
->regions
[0].delta
;
731 err
= elf_parse_dynamic_section(image
);
735 err
= elf_relocate(image
, sym_prepend
);
744 insert_image_in_list(image
);
747 mutex_unlock(&image_load_lock
);
749 dprintf("elf_load_kspace: done!\n");
754 if(image
->regions
[1].id
>= 0)
755 vm_delete_region(vm_get_kernel_aspace_id(), image
->regions
[1].id
);
756 if(image
->regions
[0].id
>= 0)
757 vm_delete_region(vm_get_kernel_aspace_id(), image
->regions
[0].id
);
765 mutex_unlock(&image_load_lock
);
768 vfs_put_vnode_ptr(vnode
);
774 static int elf_unload_image( struct elf_image_info
*image
);
776 static int elf_unlink_relocs( struct elf_image_info
*image
)
778 elf_linked_image
*link
, *next_link
;
780 for( link
= image
->linked_images
; link
; link
= next_link
) {
781 next_link
= link
->next
;
782 elf_unload_image( link
->image
);
789 static void elf_unload_image_final( struct elf_image_info
*image
)
793 for( i
= 0; i
< 2; ++i
) {
794 vm_delete_region( vm_get_kernel_aspace_id(), image
->regions
[i
].id
);
798 vfs_put_vnode_ptr( image
->vnode
);
800 remove_image_from_list(image
);
801 kfree( image
->eheader
);
805 static int elf_unload_image( struct elf_image_info
*image
)
807 if( atomic_add( &image
->ref_count
, -1 ) > 0 )
810 elf_unlink_relocs( image
);
811 elf_unload_image_final( image
);
816 int elf_unload_kspace( const char *path
)
821 struct elf_image_info
*image
;
823 fd
= sys_open(path
, STREAM_TYPE_FILE
, 0);
827 err
= vfs_get_vnode_from_fd(fd
, true, &vnode
);
831 mutex_lock(&image_load_lock
);
833 image
= find_image_by_vnode(vnode
);
835 dprintf( "Tried to unload image that wasn't loaded (%s)\n", path
);
840 err
= elf_unload_image( image
);
843 mutex_unlock(&image_load_lock
);
846 vfs_put_vnode_ptr(vnode
);
852 int elf_init(kernel_args
*ka
)
854 vm_region_info rinfo
;
857 // build a image structure for the kernel, which has already been loaded
858 kernel_image
= create_image_struct();
861 kernel_image
->regions
[0].id
= vm_find_region_by_name(vm_get_kernel_aspace_id(), "kernel_ro");
862 if(kernel_image
->regions
[0].id
< 0)
863 panic("elf_init: could not look up kernel text segment region\n");
864 vm_get_region_info(kernel_image
->regions
[0].id
, &rinfo
);
865 kernel_image
->regions
[0].start
= rinfo
.base
;
866 kernel_image
->regions
[0].size
= rinfo
.size
;
869 kernel_image
->regions
[1].id
= vm_find_region_by_name(vm_get_kernel_aspace_id(), "kernel_rw");
870 if(kernel_image
->regions
[1].id
< 0)
871 panic("elf_init: could not look up kernel data segment region\n");
872 vm_get_region_info(kernel_image
->regions
[1].id
, &rinfo
);
873 kernel_image
->regions
[1].start
= rinfo
.base
;
874 kernel_image
->regions
[1].size
= rinfo
.size
;
876 // we know where the dynamic section is
877 kernel_image
->dynamic_ptr
= (addr
)ka
->kernel_dynamic_section_addr
.start
;
879 // parse the dynamic section
880 if(elf_parse_dynamic_section(kernel_image
) < 0)
881 dprintf("elf_init: WARNING elf_parse_dynamic_section couldn't find dynamic section.\n");
883 // insert it first in the list of kernel images loaded
884 kernel_images
= NULL
;
885 insert_image_in_list(kernel_image
);
887 mutex_init(&image_lock
, "kimages_lock");
888 mutex_init(&image_load_lock
, "kimages_load_lock");