github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/pkg/memio/mmap.go (about) 1 // Copyright 2012-2020 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 // +build linux,arm linux,arm64 6 7 package memio 8 9 import ( 10 "fmt" 11 "os" 12 "syscall" 13 "unsafe" 14 ) 15 16 var ( 17 pageSize = int64(syscall.Getpagesize()) 18 ) 19 20 // mmap aligns the address and maps multiple pages when needed. 21 func mmap(f *os.File, addr int64, size int64, prot int) (mem []byte, offset int64, err error) { 22 if addr+size <= addr { 23 return nil, 0, fmt.Errorf("invalid address for size %#x", size) 24 } 25 page := addr &^ (pageSize - 1) 26 offset = addr - page 27 mapSize := offset + size 28 mem, err = syscall.Mmap(int(f.Fd()), int64(page), int(mapSize), prot, syscall.MAP_SHARED) 29 return 30 } 31 32 // Read reads data from physical memory at address addr. On x86 platforms, 33 // this uses the seek+read syscalls. On arm platforms, this uses mmap. 34 func Read(addr int64, data UintN) error { 35 f, err := os.OpenFile(memPath, os.O_RDONLY, 0) 36 if err != nil { 37 return err 38 } 39 defer f.Close() 40 41 mem, offset, err := mmap(f, addr, data.Size(), syscall.PROT_READ) 42 if err != nil { 43 return fmt.Errorf("Reading %#x/%d: %v", addr, data.Size(), err) 44 } 45 defer syscall.Munmap(mem) 46 47 // MMIO makes this a bit tricky. Reads must be conducted in one load 48 // operation. Review the generated assembly to make sure. 49 if err := data.read(unsafe.Pointer(&mem[offset])); err != nil { 50 return fmt.Errorf("Reading %#x/%d: %v", addr, data.Size(), err) 51 } 52 return nil 53 } 54 55 // Write writes data to physical memory at address addr. On x86 platforms, this 56 // uses the seek+read syscalls. On arm platforms, this uses mmap. 57 func Write(addr int64, data UintN) error { 58 f, err := os.OpenFile(memPath, os.O_RDWR, 0) 59 if err != nil { 60 return err 61 } 62 defer f.Close() 63 64 mem, offset, err := mmap(f, addr, data.Size(), syscall.PROT_WRITE) 65 if err != nil { 66 return err 67 } 68 defer syscall.Munmap(mem) 69 70 // MMIO makes this a bit tricky. Writes must be conducted in one store 71 // operation. Review the generated assembly to make sure. 72 return data.write(unsafe.Pointer(&mem[offset])) 73 }