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 }