github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/memio/archport_linux.go (about) 1 // Copyright 2012-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 //go:build (linux && amd64) || (linux && 386) 6 // +build linux,amd64 linux,386 7 8 package memio 9 10 import ( 11 "fmt" 12 "sync" 13 "syscall" 14 ) 15 16 // ArchPort is used for architectural access to a port, instead of file system 17 // level access. On the x86, this means direct, in-line in[bwl]/out[bwl] 18 // instructions, requiring an iopl system call. On other architectures, 19 // it may require special mmap setup. 20 type ArchPort struct{} 21 22 var ioplError struct { 23 sync.Once 24 err error 25 } 26 27 func iopl() error { 28 ioplError.Do(func() { 29 ioplError.err = syscall.Iopl(3) 30 }) 31 return ioplError.err 32 } 33 34 func archInl(uint16) uint32 35 func archInw(uint16) uint16 36 func archInb(uint16) uint8 37 38 // In reads data from the x86 port at address addr. Data must be Uint8, Uint16, 39 // Uint32, but not Uint64. 40 func (a *ArchPort) In(addr uint16, data UintN) error { 41 if err := iopl(); err != nil { 42 return err 43 } 44 45 switch p := data.(type) { 46 case *Uint32: 47 *p = Uint32(archInl(addr)) 48 case *Uint16: 49 *p = Uint16(archInw(addr)) 50 case *Uint8: 51 *p = Uint8(archInb(addr)) 52 default: 53 return fmt.Errorf("port data must be 8, 16 or 32 bits") 54 } 55 return nil 56 } 57 58 func archOutl(uint16, uint32) 59 func archOutw(uint16, uint16) 60 func archOutb(uint16, uint8) 61 62 // Out writes data to the x86 port at address addr. data must be Uint8, Uint16 63 // uint32, but not Uint64. 64 func (a *ArchPort) Out(addr uint16, data UintN) error { 65 if err := iopl(); err != nil { 66 return err 67 } 68 69 switch p := data.(type) { 70 case *Uint32: 71 archOutl(addr, uint32(*p)) 72 case *Uint16: 73 archOutw(addr, uint16(*p)) 74 case *Uint8: 75 archOutb(addr, uint8(*p)) 76 default: 77 return fmt.Errorf("port data must be 8, 16 or 32 bits") 78 } 79 return nil 80 } 81 82 // Close implements close 83 func (a *ArchPort) Close() error { 84 return nil 85 } 86 87 // ArchIn is deprecated. Only here to keep compatibility 88 func ArchIn(addr uint16, data UintN) error { 89 archport := &ArchPort{} 90 return archport.In(addr, data) 91 } 92 93 // ArchOut is deprecated. Only here to keep compatibility 94 func ArchOut(addr uint16, data UintN) error { 95 archport := &ArchPort{} 96 return archport.Out(addr, data) 97 }