github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/cmds/exp/fixrsdp/fixrsdp.go (about) 1 // Copyright 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 // This command copies the existing RSDP into the EBDA. This is because 6 // LinuxBoot tends to be EFI booted, which places the RSDP outside of the 7 // low 1M or the EBDA. If Linuxboot legacy boots the following operating systems, 8 // such as with kexec, they may not have a way to find the RSDP afterwards. 9 // All u-root commands that open /dev/mem should also flock it to ensure safe, 10 // sequential access 11 package main 12 13 import ( 14 "bytes" 15 "log" 16 "os" 17 "syscall" 18 19 "github.com/u-root/u-root/pkg/acpi" 20 "github.com/u-root/u-root/pkg/ebda" 21 ) 22 23 func main() { 24 // Find the RSDP. 25 base, r, err := acpi.GetRSDP() 26 if err != nil { 27 log.Fatalf("Unable to find system RSDP, got: %v", err) 28 } 29 30 rData := r.AllData() 31 rLen := len(rData) 32 33 // Check if ACPI rsdp is already in low memory 34 if base >= 0xe0000 && base+int64(rLen) < 0xffff0 { 35 log.Printf("RSDP is already in low memory at %#X, no need to fix.", base) 36 return 37 } 38 39 // Find the EBDA 40 f, err := os.OpenFile("/dev/mem", os.O_RDWR, 0) 41 if err != nil { 42 log.Fatal(err) 43 } 44 defer f.Close() 45 46 fd := int(f.Fd()) 47 if err = syscall.Flock(fd, syscall.LOCK_EX); err != nil { 48 log.Fatal(err) 49 } 50 defer syscall.Flock(fd, syscall.LOCK_UN) 51 52 e, err := ebda.ReadEBDA(f) 53 if err != nil { 54 log.Fatal(err) 55 } 56 log.Printf("EBDA starts at %#X, length %#X bytes", e.BaseOffset, e.Length) 57 58 // Scan low 1K of EBDA for an empty spot that is 16 byte aligned 59 emptyStart := 0 60 for i := 16; i < (1024-rLen) && i < (int(e.Length)-rLen); i += 16 { 61 // Check if there's an empty spot to put the RSDP table. 62 if bytes.Equal(e.Data[i:i+rLen], make([]byte, rLen)) { 63 emptyStart = i 64 log.Printf("Found empty space at %#X offset into EBDA, will copy RSDP there", emptyStart) 65 break 66 } 67 } 68 69 if emptyStart == 0 { 70 log.Fatal("Unable to find empty space to put RSDP") 71 } 72 73 copy(e.Data[emptyStart:emptyStart+rLen], rData) 74 75 if err = ebda.WriteEBDA(e, f); err != nil { 76 log.Fatal(err) 77 } 78 }