github.com/andrewsun2898/u-root@v6.0.1-0.20200616011413-4b2895c1b815+incompatible/cmds/exp/console/console.go (about) 1 // Copyright 2015-2017 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 // console implements a basic console. It establishes a pair of files 6 // to read from, the default being a UART at 0x3f8, but an alternative 7 // being just stdin and stdout. It will also set up a root file system 8 // using util.Rootfs, although this can be disabled as well. 9 // Console uses a Go version of fork_pty to start up a shell, default 10 // sh. Console runs until the shell exits and then exits itself. 11 package main 12 13 import ( 14 "flag" 15 "fmt" 16 "io" 17 "log" 18 "os" 19 20 "github.com/u-root/u-root/pkg/libinit" 21 "github.com/u-root/u-root/pkg/pty" 22 ) 23 24 var ( 25 serial = flag.String("serial", "0x3f8", "which IO device: stdio, i8042, or serial port starting with 0") 26 setupRoot = flag.Bool("setuproot", false, "Set up a root file system") 27 ) 28 29 func main() { 30 fmt.Printf("console -- starting") 31 flag.Parse() 32 33 a := flag.Args() 34 if len(a) == 0 { 35 a = []string{"/bin/sh"} 36 } 37 38 p, err := pty.New() 39 if err != nil { 40 log.Fatalf("Console exits: can't open pty: %v", err) 41 } 42 p.Command(a[0], a[1:]...) 43 // Make a good faith effort to set up root. This being 44 // a kind of init program, we do our best and keep going. 45 if *setupRoot { 46 libinit.SetEnv() 47 libinit.CreateRootfs() 48 } 49 50 in, out := io.Reader(os.Stdin), io.Writer(os.Stdout) 51 52 // This switch is kind of hokey, true, but it's also quite convenient for users. 53 switch { 54 // A raw IO port for serial console 55 case []byte(*serial)[0] == '0': 56 u, err := openUART(*serial) 57 if err != nil { 58 log.Fatalf("Console exits: sorry, can't get a uart: %v", err) 59 } 60 in, out = u, u 61 case *serial == "i8042": 62 u, err := openi8042() 63 if err != nil { 64 log.Fatalf("Console exits: sorry, can't get an i8042: %v", err) 65 } 66 in, out = u, os.Stdout 67 case *serial == "stdio": 68 default: 69 log.Fatalf("Console exits: console must be one of stdio, i8042, or an IO port with a leading 0 (e.g. 0x3f8)") 70 } 71 72 err = p.Start() 73 if err != nil { 74 log.Fatalf("Console exits: can't start %v: %v", a, err) 75 } 76 kid := p.C.Process.Pid 77 78 // You need the \r\n as we are now in raw mode! 79 fmt.Printf("Started %d\r\n", kid) 80 81 go io.Copy(out, p.Ptm) 82 83 go func() { 84 var data = make([]byte, 1) 85 for { 86 if _, err := in.Read(data); err != nil { 87 fmt.Printf("kid stdin: done\n") 88 } 89 if data[0] == '\r' { 90 if _, err := out.Write(data); err != nil { 91 log.Printf("error on echo %v: %v", data, err) 92 } 93 data[0] = '\n' 94 } 95 if _, err := p.Ptm.Write(data); err != nil { 96 log.Printf("Error writing input to ptm: %v: give up\n", err) 97 break 98 } 99 } 100 }() 101 102 if err := p.Wait(); err != nil { 103 log.Fatalf("Console exits: %v", err) 104 } 105 log.Printf("Console all done") 106 os.Exit(0) 107 }