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
);
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(struct coredump_params
*cprm
);
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 retval
= vm_mmap(file
, code_start
, code_size
, prot
,
151 flags
, SOM_PAGESTART(hpuxhdr
->exec_tfile
));
152 if (retval
< 0 && retval
> -1024)
155 data_start
= SOM_PAGESTART(hpuxhdr
->exec_dmem
);
156 data_size
= SOM_PAGEALIGN(hpuxhdr
->exec_dsize
);
157 current
->mm
->start_data
= data_start
;
158 current
->mm
->end_data
= bss_start
= data_start
+ data_size
;
159 retval
= vm_mmap(file
, data_start
, data_size
,
160 prot
| PROT_WRITE
, flags
,
161 SOM_PAGESTART(hpuxhdr
->exec_dfile
));
162 if (retval
< 0 && retval
> -1024)
165 som_brk
= bss_start
+ SOM_PAGEALIGN(hpuxhdr
->exec_bsize
);
166 current
->mm
->start_brk
= current
->mm
->brk
= som_brk
;
167 retval
= vm_mmap(NULL
, bss_start
, som_brk
- bss_start
,
168 prot
| PROT_WRITE
, MAP_FIXED
| MAP_PRIVATE
, 0);
169 if (retval
> 0 || retval
< -1024)
178 * These are the functions used to load SOM executables and shared
179 * libraries. There is no binary dependent code anywhere else.
183 load_som_binary(struct linux_binprm
* bprm
)
187 unsigned long som_entry
;
188 struct som_hdr
*som_ex
;
189 struct som_exec_auxhdr
*hpuxhdr
;
190 struct pt_regs
*regs
= current_pt_regs();
192 /* Get the exec-header */
193 som_ex
= (struct som_hdr
*) bprm
->buf
;
195 retval
= check_som_header(som_ex
);
199 /* Now read in the auxiliary header information */
202 size
= som_ex
->aux_header_size
;
203 if (size
> SOM_PAGESIZE
)
205 hpuxhdr
= kmalloc(size
, GFP_KERNEL
);
209 retval
= kernel_read(bprm
->file
, som_ex
->aux_header_location
,
210 (char *) hpuxhdr
, size
);
211 if (retval
!= size
) {
217 /* Flush all traces of the currently running executable */
218 retval
= flush_old_exec(bprm
);
222 /* OK, This is the point of no return */
223 current
->personality
= PER_HPUX
;
224 setup_new_exec(bprm
);
226 /* Set the task size for HP-UX processes such that
227 * the gateway page is outside the address space.
228 * This can be fixed later, but for now, this is much
232 current
->thread
.task_size
= 0xc0000000;
234 /* Set map base to allow enough room for hp-ux heap growth */
236 current
->thread
.map_base
= 0x80000000;
238 retval
= map_som_binary(bprm
->file
, hpuxhdr
);
242 som_entry
= hpuxhdr
->exec_entry
;
245 set_binfmt(&som_format
);
246 install_exec_creds(bprm
);
247 setup_arg_pages(bprm
, STACK_TOP
, EXSTACK_DEFAULT
);
249 create_som_tables(bprm
);
251 current
->mm
->start_stack
= bprm
->p
;
254 printk("(start_brk) %08lx\n" , (unsigned long) current
->mm
->start_brk
);
255 printk("(end_code) %08lx\n" , (unsigned long) current
->mm
->end_code
);
256 printk("(start_code) %08lx\n" , (unsigned long) current
->mm
->start_code
);
257 printk("(end_data) %08lx\n" , (unsigned long) current
->mm
->end_data
);
258 printk("(start_stack) %08lx\n" , (unsigned long) current
->mm
->start_stack
);
259 printk("(brk) %08lx\n" , (unsigned long) current
->mm
->brk
);
262 map_hpux_gateway_page(current
,current
->mm
);
264 start_thread_som(regs
, som_entry
, bprm
->p
);
274 static int load_som_library(struct file
*f
)
276 /* No lib support in SOM yet. gizza chance.. */
279 /* Install the SOM loader.
280 * N.B. We *rely* on the table being the right size with the
281 * right number of free slots...
284 static int __init
init_som_binfmt(void)
286 register_binfmt(&som_format
);
290 static void __exit
exit_som_binfmt(void)
292 /* Remove the SOM loader. */
293 unregister_binfmt(&som_format
);
296 core_initcall(init_som_binfmt
);
297 module_exit(exit_som_binfmt
);
299 MODULE_LICENSE("GPL");