| #!/bin/sh | |
| # SPDX-License-Identifier: GPL-2.0 | |
| # | |
| # Generate system call table and header files | |
| # | |
| # Copyright IBM Corp. 2018 | |
| # Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | |
| # | |
| # File path to the system call table definition. | |
| # You can set the path with the -i option. If omitted, | |
| # system call table definitions are read from standard input. | |
| # | |
| SYSCALL_TBL="" | |
| create_syscall_table_entries() | |
| { | |
| local nr abi name entry64 entry32 _ignore | |
| local temp=$(mktemp ${TMPDIR:-/tmp}/syscalltbl-common.XXXXXXXXX) | |
| ( | |
| # | |
| # Initialize with 0 to create an NI_SYSCALL for 0 | |
| # | |
| local prev_nr=0 prev_32=sys_ni_syscall prev_64=sys_ni_syscall | |
| while read nr abi name entry64 entry32 _ignore; do | |
| test x$entry32 = x- && entry32=sys_ni_syscall | |
| test x$entry64 = x- && entry64=sys_ni_syscall | |
| if test $prev_nr -eq $nr; then | |
| # | |
| # Same syscall but different ABI, just update | |
| # the respective entry point | |
| # | |
| case $abi in | |
| 32) | |
| prev_32=$entry32 | |
| ;; | |
| 64) | |
| prev_64=$entry64 | |
| ;; | |
| esac | |
| continue; | |
| else | |
| printf "%d\t%s\t%s\n" $prev_nr $prev_64 $prev_32 | |
| fi | |
| prev_nr=$nr | |
| prev_64=$entry64 | |
| prev_32=$entry32 | |
| done | |
| printf "%d\t%s\t%s\n" $prev_nr $prev_64 $prev_32 | |
| ) >> $temp | |
| # | |
| # Check for duplicate syscall numbers | |
| # | |
| if ! cat $temp |cut -f1 |uniq -d 2>&1; then | |
| echo "Error: generated system call table contains duplicate entries: $temp" >&2 | |
| exit 1 | |
| fi | |
| # | |
| # Generate syscall table | |
| # | |
| prev_nr=0 | |
| while read nr entry64 entry32; do | |
| while test $prev_nr -lt $((nr - 1)); do | |
| printf "NI_SYSCALL\n" | |
| prev_nr=$((prev_nr + 1)) | |
| done | |
| if test x$entry64 = xsys_ni_syscall && | |
| test x$entry32 = xsys_ni_syscall; then | |
| printf "NI_SYSCALL\n" | |
| else | |
| printf "SYSCALL(%s,%s)\n" $entry64 $entry32 | |
| fi | |
| prev_nr=$nr | |
| done < $temp | |
| rm $temp | |
| } | |
| generate_syscall_table() | |
| { | |
| cat <<-EoHEADER | |
| /* SPDX-License-Identifier: GPL-2.0 */ | |
| /* | |
| * Definitions for sys_call_table, each line represents an | |
| * entry in the table in the form | |
| * SYSCALL(64 bit syscall, 31 bit emulated syscall) | |
| * | |
| * This file is meant to be included from entry.S. | |
| */ | |
| #define NI_SYSCALL SYSCALL(sys_ni_syscall,sys_ni_syscall) | |
| EoHEADER | |
| grep -Ev '^(#|[[:blank:]]*$)' $SYSCALL_TBL \ | |
| |sort -k1 -n \ | |
| |create_syscall_table_entries | |
| } | |
| create_header_defines() | |
| { | |
| local nr abi name _ignore | |
| while read nr abi name _ignore; do | |
| printf "#define __NR_%s %d\n" $name $nr | |
| done | |
| } | |
| normalize_fileguard() | |
| { | |
| local fileguard="$1" | |
| echo "$1" |tr '[[:lower:]]' '[[:upper:]]' \ | |
| |sed -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g' | |
| } | |
| generate_syscall_header() | |
| { | |
| local abis=$(echo "($1)" | tr ',' '|') | |
| local filename="$2" | |
| local fileguard suffix | |
| if test "$filename"; then | |
| fileguard=$(normalize_fileguard "__UAPI_ASM_S390_$2") | |
| else | |
| case "$abis" in | |
| *64*) suffix=64 ;; | |
| *32*) suffix=32 ;; | |
| esac | |
| fileguard=$(normalize_fileguard "__UAPI_ASM_S390_SYSCALLS_$suffix") | |
| fi | |
| cat <<-EoHEADER | |
| /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | |
| #ifndef ${fileguard} | |
| #define ${fileguard} | |
| EoHEADER | |
| grep -E "^[[:digit:]]+[[:space:]]+${abis}" $SYSCALL_TBL \ | |
| |sort -k1 -n \ | |
| |create_header_defines | |
| cat <<-EoFOOTER | |
| #endif /* ${fileguard} */ | |
| EoFOOTER | |
| } | |
| __max_syscall_nr() | |
| { | |
| local abis=$(echo "($1)" | tr ',' '|') | |
| grep -E "^[[:digit:]]+[[:space:]]+${abis}" $SYSCALL_TBL \ | |
| |sed -ne 's/^\([[:digit:]]*\)[[:space:]].*/\1/p' \ | |
| |sort -n \ | |
| |tail -1 | |
| } | |
| generate_syscall_nr() | |
| { | |
| local abis="$1" | |
| local max_syscall_nr num_syscalls | |
| max_syscall_nr=$(__max_syscall_nr "$abis") | |
| num_syscalls=$((max_syscall_nr + 1)) | |
| cat <<-EoHEADER | |
| /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ | |
| #ifndef __ASM_S390_SYSCALLS_NR | |
| #define __ASM_S390_SYSCALLS_NR | |
| #define NR_syscalls ${num_syscalls} | |
| #endif /* __ASM_S390_SYSCALLS_NR */ | |
| EoHEADER | |
| } | |
| # | |
| # Parse command line arguments | |
| # | |
| do_syscall_header="" | |
| do_syscall_table="" | |
| do_syscall_nr="" | |
| output_file="" | |
| abi_list="common,64" | |
| filename="" | |
| while getopts ":HNSXi:a:f:" arg; do | |
| case $arg in | |
| a) | |
| abi_list="$OPTARG" | |
| ;; | |
| i) | |
| SYSCALL_TBL="$OPTARG" | |
| ;; | |
| f) | |
| filename=${OPTARG##*/} | |
| ;; | |
| H) | |
| do_syscall_header=1 | |
| ;; | |
| N) | |
| do_syscall_nr=1 | |
| ;; | |
| S) | |
| do_syscall_table=1 | |
| ;; | |
| X) | |
| set -x | |
| ;; | |
| :) | |
| echo "Missing argument for -$OPTARG" >&2 | |
| exit 1 | |
| ;; | |
| \?) | |
| echo "Invalid option specified" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| test "$do_syscall_header" && generate_syscall_header "$abi_list" "$filename" | |
| test "$do_syscall_table" && generate_syscall_table | |
| test "$do_syscall_nr" && generate_syscall_nr "$abi_list" | |
| exit 0 |