2014-02-05 17:48:26 +04:00
# include "defs.h"
2015-02-20 00:16:45 +03:00
# include "xlat/kexec_load_flags.h"
2014-04-26 03:30:54 +04:00
# include "xlat/kexec_arch_values.h"
2015-02-20 00:16:45 +03:00
# ifndef KEXEC_ARCH_MASK
# define KEXEC_ARCH_MASK 0xffff0000
# endif
# ifndef KEXEC_SEGMENT_MAX
# define KEXEC_SEGMENT_MAX 16
# endif
2014-02-05 17:48:26 +04:00
static void
print_kexec_segments ( struct tcb * tcp , unsigned long addr , unsigned long len )
{
# if SUPPORTED_PERSONALITIES > 1
union {
struct { u_int32_t buf , bufsz , mem , memsz ; } seg32 ;
struct { u_int64_t buf , bufsz , mem , memsz ; } seg64 ;
} seg ;
# define sizeof_seg \
( current_wordsize = = 4 ? sizeof ( seg . seg32 ) : sizeof ( seg . seg64 ) )
# define seg_buf \
( current_wordsize = = 4 ? ( uint64_t ) seg . seg32 . buf : seg . seg64 . buf )
# define seg_bufsz \
( current_wordsize = = 4 ? ( uint64_t ) seg . seg32 . bufsz : seg . seg64 . bufsz )
# define seg_mem \
( current_wordsize = = 4 ? ( uint64_t ) seg . seg32 . mem : seg . seg64 . mem )
# define seg_memsz \
( current_wordsize = = 4 ? ( uint64_t ) seg . seg32 . memsz : seg . seg64 . memsz )
# else
2015-02-20 00:16:45 +03:00
struct {
void * buf ;
size_t bufsz ;
void * mem ;
size_t memsz ;
} seg ;
2014-02-05 17:48:26 +04:00
# define sizeof_seg sizeof(seg)
2014-02-07 01:13:36 +04:00
# define seg_buf seg.buf
# define seg_bufsz seg.bufsz
# define seg_mem seg.mem
# define seg_memsz seg.memsz
2014-02-05 17:48:26 +04:00
# endif
unsigned int i , failed ;
if ( ! len ) {
tprints ( " [] " ) ;
return ;
}
if ( len > KEXEC_SEGMENT_MAX ) {
tprintf ( " %#lx " , addr ) ;
return ;
}
failed = 0 ;
tprints ( " [ " ) ;
for ( i = 0 ; i < len ; + + i ) {
if ( i )
tprints ( " , " ) ;
2015-03-21 21:50:53 +03:00
if ( umoven ( tcp , addr + i * sizeof_seg , sizeof_seg , & seg ) < 0 ) {
2014-02-05 17:48:26 +04:00
tprints ( " ? " ) ;
failed = 1 ;
break ;
}
tprintf ( " {%#lx, %lu, %#lx, %lu} " ,
( long ) seg_buf , ( unsigned long ) seg_bufsz ,
( long ) seg_mem , ( unsigned long ) seg_memsz ) ;
}
tprints ( " ] " ) ;
if ( failed )
tprintf ( " %#lx " , addr ) ;
}
2015-04-07 04:36:50 +03:00
SYS_FUNC ( kexec_load )
2014-02-05 17:48:26 +04:00
{
unsigned long n ;
if ( exiting ( tcp ) )
return 0 ;
/* entry, nr_segments */
tprintf ( " %#lx, %lu, " , tcp - > u_arg [ 0 ] , tcp - > u_arg [ 1 ] ) ;
/* segments */
print_kexec_segments ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
tprints ( " , " ) ;
/* flags */
n = tcp - > u_arg [ 3 ] ;
printxval ( kexec_arch_values , n & KEXEC_ARCH_MASK , " KEXEC_ARCH_??? " ) ;
n & = ~ KEXEC_ARCH_MASK ;
if ( n ) {
tprints ( " | " ) ;
2015-02-20 00:16:45 +03:00
printflags ( kexec_load_flags , n , " KEXEC_??? " ) ;
2014-02-05 17:48:26 +04:00
}
return 0 ;
}