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