github.com/xyproto/u-root@v6.0.1-0.20200302025726-5528e0c77a3c+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 }