b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * arch/um/kernel/elf_aux.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Scan the Elf auxiliary vector provided by the host to extract
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) * information about vsyscall-page, etc.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * Copyright (C) 2004 Fujitsu Siemens Computers GmbH
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <elf.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <stddef.h>
37185b3324087 (Al Viro 2012-10-08 03:27:32 +0100 13) #include <init.h>
37185b3324087 (Al Viro 2012-10-08 03:27:32 +0100 14) #include <elf_user.h>
37185b3324087 (Al Viro 2012-10-08 03:27:32 +0100 15) #include <mem_user.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) typedef Elf32_auxv_t elf_auxv_t;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18)
c538b391a7e8f (Jeff Dike 2007-02-10 01:44:26 -0800 19) /* These are initialized very early in boot and never changed */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) char * elf_aux_platform;
b743ac54e54ca (Richard Weinberger 2011-07-25 17:12:52 -0700 21) extern long elf_aux_hwcap;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) unsigned long vsyscall_ehdr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23) unsigned long vsyscall_end;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) unsigned long __kernel_vsyscall;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 25)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) __init void scan_elf_aux( char **envp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 28) long page_size = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 29) elf_auxv_t * auxv;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 30)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 31) while ( *envp++ != NULL) ;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 32)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 33) for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 34) switch ( auxv->a_type ) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35) case AT_SYSINFO:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 36) __kernel_vsyscall = auxv->a_un.a_val;
14251809b1921 (Jeff Dike 2007-02-28 20:13:31 -0800 37) /* See if the page is under TASK_SIZE */
14251809b1921 (Jeff Dike 2007-02-28 20:13:31 -0800 38) if (__kernel_vsyscall < (unsigned long) envp)
14251809b1921 (Jeff Dike 2007-02-28 20:13:31 -0800 39) __kernel_vsyscall = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 41) case AT_SYSINFO_EHDR:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) vsyscall_ehdr = auxv->a_un.a_val;
a502a3593c7aa (Jeff Dike 2005-07-29 14:03:33 -0700 43) /* See if the page is under TASK_SIZE */
a502a3593c7aa (Jeff Dike 2005-07-29 14:03:33 -0700 44) if (vsyscall_ehdr < (unsigned long) envp)
a502a3593c7aa (Jeff Dike 2005-07-29 14:03:33 -0700 45) vsyscall_ehdr = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) case AT_HWCAP:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) elf_aux_hwcap = auxv->a_un.a_val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 50) case AT_PLATFORM:
da00d9a546655 (Jeff Dike 2005-06-08 15:48:01 -0700 51) /* elf.h removed the pointer elements from
da00d9a546655 (Jeff Dike 2005-06-08 15:48:01 -0700 52) * a_un, so we have to use a_val, which is
da00d9a546655 (Jeff Dike 2005-06-08 15:48:01 -0700 53) * all that's left.
da00d9a546655 (Jeff Dike 2005-06-08 15:48:01 -0700 54) */
64b7673f91c0c (Jeff Dike 2005-09-16 19:27:48 -0700 55) elf_aux_platform =
64b7673f91c0c (Jeff Dike 2005-09-16 19:27:48 -0700 56) (char *) (long) auxv->a_un.a_val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 57) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 58) case AT_PAGESZ:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 59) page_size = auxv->a_un.a_val;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 62) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 63) if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 64) ! elf_aux_hwcap || ! elf_aux_platform ||
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 65) ! page_size || (vsyscall_ehdr % page_size) ) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 66) __kernel_vsyscall = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) vsyscall_ehdr = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68) elf_aux_hwcap = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 69) elf_aux_platform = "i586";
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) else {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) vsyscall_end = vsyscall_ehdr + page_size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) }