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/a.out.h>
33 #include <asm/uaccess.h>
34 #include <asm/pgtable.h>
37 #include <linux/elf.h>
39 static int load_som_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
);
40 static int load_som_library(struct file
*);
43 * If we don't support core dumping, then supply a NULL so we
47 static int som_core_dump(long signr
, struct pt_regs
*regs
, unsigned long limit
);
49 #define som_core_dump NULL
52 #define SOM_PAGESTART(_v) ((_v) & ~(unsigned long)(SOM_PAGESIZE-1))
53 #define SOM_PAGEOFFSET(_v) ((_v) & (SOM_PAGESIZE-1))
54 #define SOM_PAGEALIGN(_v) (((_v) + SOM_PAGESIZE - 1) & ~(SOM_PAGESIZE - 1))
56 static struct linux_binfmt som_format
= {
57 .module
= THIS_MODULE
,
58 .load_binary
= load_som_binary
,
59 .load_shlib
= load_som_library
,
60 .core_dump
= som_core_dump
,
61 .min_coredump
= SOM_PAGESIZE
65 * create_som_tables() parses the env- and arg-strings in new user
66 * memory and creates the pointer tables from them, and puts their
67 * addresses on the "stack", returning the new stack pointer value.
69 static void create_som_tables(struct linux_binprm
*bprm
)
72 int argc
= bprm
->argc
;
73 int envc
= bprm
->envc
;
77 /* Word-align the stack pointer */
78 sp
= (unsigned long *)((bprm
->p
+ 3) & ~3);
85 __put_user((unsigned long) envp
,++sp
);
86 __put_user((unsigned long) argv
,++sp
);
88 __put_user(argc
, ++sp
);
90 bprm
->p
= (unsigned long) sp
;
92 p
= current
->mm
->arg_start
;
94 __put_user((char *)p
,argv
++);
95 p
+= strlen_user((char *)p
);
97 __put_user(NULL
, argv
);
98 current
->mm
->arg_end
= current
->mm
->env_start
= p
;
100 __put_user((char *)p
,envp
++);
101 p
+= strlen_user((char *)p
);
103 __put_user(NULL
, envp
);
104 current
->mm
->env_end
= p
;
107 static int check_som_header(struct som_hdr
*som_ex
)
109 int *buf
= (int *)som_ex
;
112 if (som_ex
->system_id
!= SOM_SID_PARISC_1_0
&&
113 som_ex
->system_id
!= SOM_SID_PARISC_1_1
&&
114 som_ex
->system_id
!= SOM_SID_PARISC_2_0
)
117 if (som_ex
->a_magic
!= SOM_EXEC_NONSHARE
&&
118 som_ex
->a_magic
!= SOM_EXEC_SHARE
&&
119 som_ex
->a_magic
!= SOM_EXEC_DEMAND
)
122 if (som_ex
->version_id
!= SOM_ID_OLD
&&
123 som_ex
->version_id
!= SOM_ID_NEW
)
135 static int map_som_binary(struct file
*file
,
136 const struct som_exec_auxhdr
*hpuxhdr
)
138 unsigned long code_start
, code_size
, data_start
, data_size
;
139 unsigned long bss_start
, som_brk
;
141 int prot
= PROT_READ
| PROT_EXEC
;
142 int flags
= MAP_FIXED
|MAP_PRIVATE
|MAP_DENYWRITE
|MAP_EXECUTABLE
;
144 mm_segment_t old_fs
= get_fs();
147 code_start
= SOM_PAGESTART(hpuxhdr
->exec_tmem
);
148 code_size
= SOM_PAGEALIGN(hpuxhdr
->exec_tsize
);
149 current
->mm
->start_code
= code_start
;
150 current
->mm
->end_code
= code_start
+ code_size
;
151 down_write(¤t
->mm
->mmap_sem
);
152 retval
= do_mmap(file
, code_start
, code_size
, prot
,
153 flags
, SOM_PAGESTART(hpuxhdr
->exec_tfile
));
154 up_write(¤t
->mm
->mmap_sem
);
155 if (retval
< 0 && retval
> -1024)
158 data_start
= SOM_PAGESTART(hpuxhdr
->exec_dmem
);
159 data_size
= SOM_PAGEALIGN(hpuxhdr
->exec_dsize
);
160 current
->mm
->start_data
= data_start
;
161 current
->mm
->end_data
= bss_start
= data_start
+ data_size
;
162 down_write(¤t
->mm
->mmap_sem
);
163 retval
= do_mmap(file
, data_start
, data_size
,
164 prot
| PROT_WRITE
, flags
,
165 SOM_PAGESTART(hpuxhdr
->exec_dfile
));
166 up_write(¤t
->mm
->mmap_sem
);
167 if (retval
< 0 && retval
> -1024)
170 som_brk
= bss_start
+ SOM_PAGEALIGN(hpuxhdr
->exec_bsize
);
171 current
->mm
->start_brk
= current
->mm
->brk
= som_brk
;
172 down_write(¤t
->mm
->mmap_sem
);
173 retval
= do_mmap(NULL
, bss_start
, som_brk
- bss_start
,
174 prot
| PROT_WRITE
, MAP_FIXED
| MAP_PRIVATE
, 0);
175 up_write(¤t
->mm
->mmap_sem
);
176 if (retval
> 0 || retval
< -1024)
185 * These are the functions used to load SOM executables and shared
186 * libraries. There is no binary dependent code anywhere else.
190 load_som_binary(struct linux_binprm
* bprm
, struct pt_regs
* regs
)
195 unsigned long som_entry
;
196 struct som_hdr
*som_ex
;
197 struct som_exec_auxhdr
*hpuxhdr
;
198 struct files_struct
*files
;
200 /* Get the exec-header */
201 som_ex
= (struct som_hdr
*) bprm
->buf
;
203 retval
= check_som_header(som_ex
);
207 /* Now read in the auxiliary header information */
210 size
= som_ex
->aux_header_size
;
211 if (size
> SOM_PAGESIZE
)
213 hpuxhdr
= kmalloc(size
, GFP_KERNEL
);
217 retval
= kernel_read(bprm
->file
, som_ex
->aux_header_location
,
218 (char *) hpuxhdr
, size
);
219 if (retval
!= size
) {
225 files
= current
->files
; /* Refcounted so ok */
226 retval
= unshare_files();
229 if (files
== current
->files
) {
230 put_files_struct(files
);
234 retval
= get_unused_fd();
237 get_file(bprm
->file
);
238 fd_install(som_exec_fileno
= retval
, bprm
->file
);
240 /* Flush all traces of the currently running executable */
241 retval
= flush_old_exec(bprm
);
245 /* OK, This is the point of no return */
246 current
->flags
&= ~PF_FORKNOEXEC
;
247 current
->personality
= PER_HPUX
;
249 /* Set the task size for HP-UX processes such that
250 * the gateway page is outside the address space.
251 * This can be fixed later, but for now, this is much
255 current
->thread
.task_size
= 0xc0000000;
257 /* Set map base to allow enough room for hp-ux heap growth */
259 current
->thread
.map_base
= 0x80000000;
261 retval
= map_som_binary(bprm
->file
, hpuxhdr
);
265 som_entry
= hpuxhdr
->exec_entry
;
268 set_binfmt(&som_format
);
270 setup_arg_pages(bprm
, STACK_TOP
, EXSTACK_DEFAULT
);
272 create_som_tables(bprm
);
274 current
->mm
->start_stack
= bprm
->p
;
277 printk("(start_brk) %08lx\n" , (unsigned long) current
->mm
->start_brk
);
278 printk("(end_code) %08lx\n" , (unsigned long) current
->mm
->end_code
);
279 printk("(start_code) %08lx\n" , (unsigned long) current
->mm
->start_code
);
280 printk("(end_data) %08lx\n" , (unsigned long) current
->mm
->end_data
);
281 printk("(start_stack) %08lx\n" , (unsigned long) current
->mm
->start_stack
);
282 printk("(brk) %08lx\n" , (unsigned long) current
->mm
->brk
);
285 map_hpux_gateway_page(current
,current
->mm
);
287 start_thread_som(regs
, som_entry
, bprm
->p
);
288 if (current
->ptrace
& PT_PTRACED
)
289 send_sig(SIGTRAP
, current
, 0);
299 static int load_som_library(struct file
*f
)
301 /* No lib support in SOM yet. gizza chance.. */
304 /* Install the SOM loader.
305 * N.B. We *rely* on the table being the right size with the
306 * right number of free slots...
309 static int __init
init_som_binfmt(void)
311 return register_binfmt(&som_format
);
314 static void __exit
exit_som_binfmt(void)
316 /* Remove the SOM loader. */
317 unregister_binfmt(&som_format
);
320 core_initcall(init_som_binfmt
);
321 module_exit(exit_som_binfmt
);