github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/boot/kexec/kexec_load_linux.go (about) 1 // Copyright 2015-2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package kexec 6 7 import ( 8 "fmt" 9 "syscall" 10 "unsafe" 11 12 "golang.org/x/sys/unix" 13 ) 14 15 // Load loads the given segments into memory to be executed on a kexec-reboot. 16 // 17 // It is assumed that segments is made up of the next kernel's code and text 18 // segments, and that `entry` is the entry point, either kernel entry point or trampoline. 19 // 20 // Load will align segments to page boundaries and deduplicate overlapping ranges. 21 func Load(entry uintptr, segments Segments, flags uint64) error { 22 for i := range segments { 23 segments[i] = AlignPhys(segments[i]) 24 } 25 26 segments = Dedup(segments) 27 if !segments.PhysContains(entry) { 28 return fmt.Errorf("entry point %#v is not covered by any segment", entry) 29 } 30 31 return rawLoad(entry, segments, flags) 32 } 33 34 // ErrKexec is returned by Load if the kexec failed. It describes entry point, 35 // flags, errno and kernel layout. 36 type ErrKexec struct { 37 Entry uintptr 38 Segments []Segment 39 Flags uint64 40 Errno syscall.Errno 41 } 42 43 // Error implements error. 44 func (e ErrKexec) Error() string { 45 return fmt.Sprintf("kexec_load(entry=%#x, segments=%s, flags %#x) = errno %s", e.Entry, e.Segments, e.Flags, e.Errno) 46 } 47 48 // rawLoad is a wrapper around kexec_load(2) syscall. 49 // Preconditions: 50 // - segments must not overlap 51 // - segments must be full pages 52 func rawLoad(entry uintptr, segments []Segment, flags uint64) error { 53 if _, _, errno := unix.Syscall6( 54 unix.SYS_KEXEC_LOAD, 55 entry, 56 uintptr(len(segments)), 57 uintptr(unsafe.Pointer(&segments[0])), 58 uintptr(flags), 59 0, 0); errno != 0 { 60 return ErrKexec{ 61 Entry: entry, 62 Segments: segments, 63 Flags: flags, 64 Errno: errno, 65 } 66 } 67 return nil 68 }