github.com/shaardie/u-root@v4.0.1-0.20190127173353-f24a1c26aa2e+incompatible/pkg/io/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 io 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), 30 int(mapSize), prot, syscall.MAP_SHARED) 31 return 32 } 33 34 // Read reads data from physical memory at address addr. On x86 platforms, 35 // this uses the seek+read syscalls. On arm platforms, this uses mmap. 36 func Read(addr int64, data UintN) error { 37 f, err := os.OpenFile(memPath, os.O_RDONLY, 0) 38 if err != nil { 39 return err 40 } 41 defer f.Close() 42 43 mem, offset, err := mmap(f, addr, data.Size(), syscall.PROT_READ) 44 if err != nil { 45 return err 46 } 47 defer syscall.Munmap(mem) 48 49 // MMIO makes this a bit tricky. Reads must be conducted in one load 50 // operation. Review the generated assembly to make sure. 51 return data.read(unsafe.Pointer(&mem[offset])) 52 } 53 54 // Write writes data to physical memory at address addr. On x86 platforms, this 55 // uses the seek+read syscalls. On arm platforms, this uses mmap. 56 func Write(addr int64, data UintN) error { 57 f, err := os.OpenFile(memPath, os.O_RDWR, 0) 58 if err != nil { 59 return err 60 } 61 defer f.Close() 62 63 mem, offset, err := mmap(f, addr, data.Size(), syscall.PROT_WRITE) 64 if err != nil { 65 return err 66 } 67 defer syscall.Munmap(mem) 68 69 // MMIO makes this a bit tricky. Writes must be conducted in one store 70 // operation. Review the generated assembly to make sure. 71 return data.write(unsafe.Pointer(&mem[offset])) 72 }