github.com/system-transparency/u-root@v6.0.1-0.20190919065413-ed07a650de4c+incompatible/cmds/core/io/io.go (about)

     1  // Copyright 2010-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  // io reads and writes to physical memory and ports.
     6  //
     7  // Synopsis:
     8  //     io (r{b,w,l,q} address)...
     9  //     io (w{b,w,l,q} address value)...
    10  //     # x86 only:
    11  //     io (in{b,w,l} address)
    12  //     io (out{b,w,l} address value)...
    13  //
    14  // Description:
    15  //     io lets you read/write 1/2/4/8-bytes to memory with the {r,w}{b,w,l,q}
    16  //     commands respectively.
    17  //
    18  //     On x86 platforms, {in,out}{b,w,l} allow for port io.
    19  //
    20  // Examples:
    21  //     # Read 8-bytes from address 0x10000 and 0x10000
    22  //     io rq 0x10000 rq 0x10008
    23  //     # Write to the serial port on x86
    24  //     io outb 0x3f8 50
    25  package main
    26  
    27  import (
    28  	"fmt"
    29  	"log"
    30  	"os"
    31  	"strconv"
    32  
    33  	"github.com/u-root/u-root/pkg/memio"
    34  )
    35  
    36  type cmd struct {
    37  	f                 func(addr int64, data memio.UintN) error
    38  	addrBits, valBits int
    39  }
    40  
    41  var (
    42  	readCmds = map[string]cmd{
    43  		"rb": {memio.Read, 64, 8},
    44  		"rw": {memio.Read, 64, 16},
    45  		"rl": {memio.Read, 64, 32},
    46  		"rq": {memio.Read, 64, 64},
    47  	}
    48  	writeCmds = map[string]cmd{
    49  		"wb": {memio.Write, 64, 8},
    50  		"ww": {memio.Write, 64, 16},
    51  		"wl": {memio.Write, 64, 32},
    52  		"wq": {memio.Write, 64, 64},
    53  	}
    54  )
    55  
    56  var usageMsg = `io (r{b,w,l,q} address)...
    57  io (w{b,w,l,q} address value)...
    58  `
    59  
    60  func usage() {
    61  	fmt.Print(usageMsg)
    62  	os.Exit(1)
    63  }
    64  
    65  // newInt constructs a UintN with the specified value and bits.
    66  func newInt(val uint64, bits int) memio.UintN {
    67  	switch bits {
    68  	case 8:
    69  		val := memio.Uint8(int8(val))
    70  		return &val
    71  	case 16:
    72  		val := memio.Uint16(uint16(val))
    73  		return &val
    74  	case 32:
    75  		val := memio.Uint32(uint32(val))
    76  		return &val
    77  	case 64:
    78  		val := memio.Uint64(uint64(val))
    79  		return &val
    80  	default:
    81  		panic(fmt.Sprintf("invalid number of bits %d", bits))
    82  	}
    83  }
    84  
    85  func main() {
    86  	if len(os.Args) < 3 {
    87  		usage()
    88  	}
    89  	os.Args = os.Args[1:]
    90  
    91  	// To avoid the command list from being partially executed when the
    92  	// args fail to parse, queue them up and run all at once at the end.
    93  	queue := []func(){}
    94  
    95  	for len(os.Args) > 0 {
    96  		var cmdStr string
    97  		cmdStr, os.Args = os.Args[0], os.Args[1:]
    98  		if c, ok := readCmds[cmdStr]; ok {
    99  			// Parse arguments.
   100  			if len(os.Args) < 1 {
   101  				usage()
   102  			}
   103  			var addrStr string
   104  			addrStr, os.Args = os.Args[0], os.Args[1:]
   105  			addr, err := strconv.ParseUint(addrStr, 0, c.addrBits)
   106  			if err != nil {
   107  				log.Fatal(err)
   108  			}
   109  
   110  			queue = append(queue, func() {
   111  				// Read from addr and print.
   112  				data := newInt(0, c.valBits)
   113  				if err := c.f(int64(addr), data); err != nil {
   114  					log.Fatal(err)
   115  				}
   116  				fmt.Printf("%s\n", data)
   117  			})
   118  		} else if c, ok := writeCmds[cmdStr]; ok {
   119  			// Parse arguments.
   120  			if len(os.Args) < 2 {
   121  				usage()
   122  			}
   123  			var addrStr, dataStr string
   124  			addrStr, dataStr, os.Args = os.Args[0], os.Args[1], os.Args[2:]
   125  			addr, err := strconv.ParseUint(addrStr, 0, c.addrBits)
   126  			if err != nil {
   127  				log.Fatal(err)
   128  			}
   129  			value, err := strconv.ParseUint(dataStr, 0, c.valBits)
   130  			if err != nil {
   131  				log.Fatal(err)
   132  			}
   133  
   134  			queue = append(queue, func() {
   135  				// Write data to addr.
   136  				data := newInt(value, c.valBits)
   137  				if err := c.f(int64(addr), data); err != nil {
   138  					log.Fatal(err)
   139  				}
   140  			})
   141  		} else {
   142  			usage()
   143  		}
   144  	}
   145  
   146  	// Run all commands.
   147  	for _, c := range queue {
   148  		c()
   149  	}
   150  }