18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  arch/um/kernel/elf_aux.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Scan the Elf auxiliary vector provided by the host to extract
68c2ecf20Sopenharmony_ci *  information about vsyscall-page, etc.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Copyright (C) 2004 Fujitsu Siemens Computers GmbH
98c2ecf20Sopenharmony_ci *  Author: Bodo Stroesser (bodo.stroesser@fujitsu-siemens.com)
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#include <elf.h>
128c2ecf20Sopenharmony_ci#include <stddef.h>
138c2ecf20Sopenharmony_ci#include <init.h>
148c2ecf20Sopenharmony_ci#include <elf_user.h>
158c2ecf20Sopenharmony_ci#include <mem_user.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_citypedef Elf32_auxv_t elf_auxv_t;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* These are initialized very early in boot and never changed */
208c2ecf20Sopenharmony_cichar * elf_aux_platform;
218c2ecf20Sopenharmony_ciextern long elf_aux_hwcap;
228c2ecf20Sopenharmony_ciunsigned long vsyscall_ehdr;
238c2ecf20Sopenharmony_ciunsigned long vsyscall_end;
248c2ecf20Sopenharmony_ciunsigned long __kernel_vsyscall;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci__init void scan_elf_aux( char **envp)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	long page_size = 0;
298c2ecf20Sopenharmony_ci	elf_auxv_t * auxv;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	while ( *envp++ != NULL) ;
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	for ( auxv = (elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) {
348c2ecf20Sopenharmony_ci		switch ( auxv->a_type ) {
358c2ecf20Sopenharmony_ci			case AT_SYSINFO:
368c2ecf20Sopenharmony_ci				__kernel_vsyscall = auxv->a_un.a_val;
378c2ecf20Sopenharmony_ci				/* See if the page is under TASK_SIZE */
388c2ecf20Sopenharmony_ci				if (__kernel_vsyscall < (unsigned long) envp)
398c2ecf20Sopenharmony_ci					__kernel_vsyscall = 0;
408c2ecf20Sopenharmony_ci				break;
418c2ecf20Sopenharmony_ci			case AT_SYSINFO_EHDR:
428c2ecf20Sopenharmony_ci				vsyscall_ehdr = auxv->a_un.a_val;
438c2ecf20Sopenharmony_ci				/* See if the page is under TASK_SIZE */
448c2ecf20Sopenharmony_ci				if (vsyscall_ehdr < (unsigned long) envp)
458c2ecf20Sopenharmony_ci					vsyscall_ehdr = 0;
468c2ecf20Sopenharmony_ci				break;
478c2ecf20Sopenharmony_ci			case AT_HWCAP:
488c2ecf20Sopenharmony_ci				elf_aux_hwcap = auxv->a_un.a_val;
498c2ecf20Sopenharmony_ci				break;
508c2ecf20Sopenharmony_ci			case AT_PLATFORM:
518c2ecf20Sopenharmony_ci                                /* elf.h removed the pointer elements from
528c2ecf20Sopenharmony_ci                                 * a_un, so we have to use a_val, which is
538c2ecf20Sopenharmony_ci                                 * all that's left.
548c2ecf20Sopenharmony_ci                                 */
558c2ecf20Sopenharmony_ci				elf_aux_platform =
568c2ecf20Sopenharmony_ci					(char *) (long) auxv->a_un.a_val;
578c2ecf20Sopenharmony_ci				break;
588c2ecf20Sopenharmony_ci			case AT_PAGESZ:
598c2ecf20Sopenharmony_ci				page_size = auxv->a_un.a_val;
608c2ecf20Sopenharmony_ci				break;
618c2ecf20Sopenharmony_ci		}
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci	if ( ! __kernel_vsyscall || ! vsyscall_ehdr ||
648c2ecf20Sopenharmony_ci	     ! elf_aux_hwcap || ! elf_aux_platform ||
658c2ecf20Sopenharmony_ci	     ! page_size || (vsyscall_ehdr % page_size) ) {
668c2ecf20Sopenharmony_ci		__kernel_vsyscall = 0;
678c2ecf20Sopenharmony_ci		vsyscall_ehdr = 0;
688c2ecf20Sopenharmony_ci		elf_aux_hwcap = 0;
698c2ecf20Sopenharmony_ci		elf_aux_platform = "i586";
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	else {
728c2ecf20Sopenharmony_ci		vsyscall_end = vsyscall_ehdr + page_size;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci}
75