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  }