2 * linux/fs/binfmt_som.c
4 * These are the functions used to load SOM format executables as used
7 * Copyright 1999 Matthew Wilcox <willy@bofh.ai>
8 * based on binfmt_elf which is
9 * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
12 #include <linux/module.h>
15 #include <linux/stat.h>
16 #include <linux/sched.h>
18 #include <linux/mman.h>
19 #include <linux/errno.h>
20 #include <linux/signal.h>
21 #include <linux/binfmts.h>
22 #include <linux/som.h>
23 #include <linux/string.h>
24 #include <linux/file.h>
25 #include <linux/fcntl.h>
26 #include <linux/ptrace.h>
27 #include <linux/slab.h>
28 #include <linux/shm.h>
29 #include <linux/personality.h>
30 #include <linux/init.h>
32 #include <asm/uaccess.h>
33 #include <asm/pgtable.h>
36 #include <linux/elf.h>
38 static int load_som_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
);
39 static int load_som_library(struct file
*);
42 * If we don't support core dumping, then supply a NULL so we
46 static int som_core_dump(long signr
, struct pt_regs
*regs
, unsigned long limit
);
48 #define som_core_dump NULL
51 #define SOM_PAGESTART(_v) ((_v) & ~(unsigned long)(SOM_PAGESIZE-1))
52 #define SOM_PAGEOFFSET(_v) ((_v) & (SOM_PAGESIZE-1))
53 #define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1))
55 static struct linux_binfmt som_format
= {
56 .module
= THIS_MODULE
,
57 .load_binary
= load_som_binary
,
58 .load_shlib
= load_som_library
,
59 .core_dump
= som_core_dump
,
60 .min_coredump
= SOM_PAGESIZE
64 * create_som_tables() parses the env- and arg-strings in new user
65 * memory and creates the pointer tables from them, and puts their
66 * addresses on the "stack", returning the new stack pointer value.
68 static void create_som_tables(struct linux_binprm
*bprm
)
71 int argc
= bprm
->argc
;
72 int envc
= bprm
->envc
;
76 /* Word-align the stack pointer */
77 sp
= (unsigned long *)((bprm
->p
+ 3) & ~3);
84 __put_user((unsigned long) envp
,++sp
);
85 __put_user((unsigned long) argv
,++sp
);
87 __put_user(argc
, ++sp
);
89 bprm
->p
= (unsigned long) sp
;
91 p
= current
->mm
->arg_start
;
93 __put_user((char *)p
,argv
++);
94 p
+= strlen_user((char *)p
);
96 __put_user(NULL
, argv
);
97 current
->mm
->arg_end
= current
->mm
->env_start
= p
;
99 __put_user((char *)p
,envp
++);
100 p
+= strlen_user((char *)p
);
102 __put_user(NULL
, envp
);
103 current
->mm
->env_end
= p
;
106 static int check_som_header(struct som_hdr
*som_ex
)
108 int *buf
= (int *)som_ex
;
111 if (som_ex
->system_id
!= SOM_SID_PARISC_1_0
&&
112 som_ex
->system_id
!= SOM_SID_PARISC_1_1
&&
113 som_ex
->system_id
!= SOM_SID_PARISC_2_0
)
116 if (som_ex
->a_magic
!= SOM_EXEC_NONSHARE
&&
117 som_ex
->a_magic
!= SOM_EXEC_SHARE
&&
118 som_ex
->a_magic
!= SOM_EXEC_DEMAND
)
121 if (som_ex
->version_id
!= SOM_ID_OLD
&&
122 som_ex
->version_id
!= SOM_ID_NEW
)
134 static int map_som_binary(struct file
*file
,
135 const struct som_exec_auxhdr
*hpuxhdr
)
137 unsigned long code_start
, code_size
, data_start
, data_size
;
138 unsigned long bss_start
, som_brk
;
140 int prot
= PROT_READ
| PROT_EXEC
;
141 int flags
= MAP_FIXED
|MAP_PRIVATE
|MAP_DENYWRITE
|MAP_EXECUTABLE
;
143 mm_segment_t old_fs
= get_fs();
146 code_start
= SOM_PAGESTART(hpuxhdr
->exec_tmem
);
147 code_size
= SOM_PAGEALIGN(hpuxhdr
->exec_tsize
);
148 current
->mm
->start_code
= code_start
;
149 current
->mm
->end_code
= code_start
+ code_size
;
150 down_write(¤t
->mm
->mmap_sem
);
151 retval
= do_mmap(file
, code_start
, code_size
, prot
,
152 flags
, SOM_PAGESTART(hpuxhdr
->exec_tfile
));
153 up_write(¤t
->mm
->mmap_sem
);
154 if (retval
< 0 && retval
> -1024)
157 data_start
= SOM_PAGESTART(hpuxhdr
->exec_dmem
);
158 data_size
= SOM_PAGEALIGN(hpuxhdr
->exec_dsize
);
159 current
->mm
->start_data
= data_start
;
160 current
->mm
->end_data
= bss_start
= data_start
+ data_size
;
161 down_write(¤t
->mm
->mmap_sem
);
162 retval
= do_mmap(file
, data_start
, data_size
,
163 prot
| PROT_WRITE
, flags
,
164 SOM_PAGESTART(hpuxhdr
->exec_dfile
));
165 up_write(¤t
->mm
->mmap_sem
);
166 if (retval
< 0 && retval
> -1024)
169 som_brk
= bss_start
+ SOM_PAGEALIGN(hpuxhdr
->exec_bsize
);
170 current
->mm
->start_brk
= current
->mm
->brk
= som_brk
;
171 down_write(¤t
->mm
->mmap_sem
);
172 retval
= do_mmap(NULL
, bss_start
, som_brk
- bss_start
,
173 prot
| PROT_WRITE
, MAP_FIXED
| MAP_PRIVATE
, 0);
174 up_write(¤t
->mm
->mmap_sem
);
175 if (retval
> 0 || retval
< -1024)
184 * These are the functions used to load SOM executables and shared
185 * libraries. There is no binary dependent code anywhere else.
189 load_som_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
)
194 unsigned long som_entry
;
195 struct som_hdr
*som_ex
;
196 struct som_exec_auxhdr
*hpuxhdr
;
197 struct files_struct
*files
;
199 /* Get the exec-header */
200 som_ex
= (struct som_hdr
*) bprm
->buf
;
202 retval
= check_som_header(som_ex
);
206 /* Now read in the auxiliary header information */
209 size
= som_ex
->aux_header_size
;
210 if (size
> SOM_PAGESIZE
)
212 hpuxhdr
= kmalloc(size
, GFP_KERNEL
);
216 retval
= kernel_read(bprm
->file
, som_ex
->aux_header_location
,
217 (char *) hpuxhdr
, size
);
218 if (retval
!= size
) {
224 files
= current
->files
; /* Refcounted so ok */
225 retval
= unshare_files();
228 if (files
== current
->files
) {
229 put_files_struct(files
);
233 retval
= get_unused_fd();
236 get_file(bprm
->file
);
237 fd_install(som_exec_fileno
= retval
, bprm
->file
);
239 /* Flush all traces of the currently running executable */
240 retval
= flush_old_exec(bprm
);
244 /* OK, This is the point of no return */
245 current
->flags
&= ~PF_FORKNOEXEC
;
246 current
->personality
= PER_HPUX
;
248 /* Set the task size for HP-UX processes such that
249 * the gateway page is outside the address space.
250 * This can be fixed later, but for now, this is much
254 current
->thread
.task_size
= 0xc0000000;
256 /* Set map base to allow enough room for hp-ux heap growth */
258 current
->thread
.map_base
= 0x80000000;
260 retval
= map_som_binary(bprm
->file
, hpuxhdr
);
264 som_entry
= hpuxhdr
->exec_entry
;
267 set_binfmt(&som_format
);
269 setup_arg_pages(bprm
, STACK_TOP
, EXSTACK_DEFAULT
);
271 create_som_tables(bprm
);
273 current
->mm
->start_stack
= bprm
->p
;
276 printk("(start_brk) %08lx\n" , (unsigned long) current
->mm
->start_brk
);
277 printk("(end_code) %08lx\n" , (unsigned long) current
->mm
->end_code
);
278 printk("(start_code) %08lx\n" , (unsigned long) current
->mm
->start_code
);
279 printk("(end_data) %08lx\n" , (unsigned long) current
->mm
->end_data
);
280 printk("(start_stack) %08lx\n" , (unsigned long) current
->mm
->start_stack
);
281 printk("(brk) %08lx\n" , (unsigned long) current
->mm
->brk
);
284 map_hpux_gateway_page(current
,current
->mm
);
286 start_thread_som(regs
, som_entry
, bprm
->p
);
287 if (current
->ptrace
& PT_PTRACED
)
288 send_sig(SIGTRAP
, current
, 0);
298 static int load_som_library(struct file
*f
)
300 /* No lib support in SOM yet. gizza chance.. */
303 /* Install the SOM loader.
304 * N.B. We *rely* on the table being the right size with the
305 * right number of free slots...
308 static int __init
init_som_binfmt(void)
310 return register_binfmt(&som_format
);
313 static void __exit
exit_som_binfmt(void)
315 /* Remove the SOM loader. */
316 unregister_binfmt(&som_format
);
319 core_initcall(init_som_binfmt
);
320 module_exit(exit_som_binfmt
);