gitlab.com/apertussolutions/u-root@v7.0.0+incompatible/cmds/core/io/io.go (about)

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