github.com/jspc/eggos@v0.5.1-0.20221028160421-556c75c878a5/kernel/env.go (about) 1 package kernel 2 3 import ( 4 "unsafe" 5 6 "github.com/jspc/eggos/drivers/multiboot" 7 "github.com/jspc/eggos/kernel/sys" 8 "gvisor.dev/gvisor/pkg/abi/linux" 9 ) 10 11 //go:nosplit 12 func envput(pbuf *[]byte, v uintptr) uintptr { 13 buf := *pbuf 14 p := unsafe.Pointer(&buf[0]) 15 // *p = v 16 *(*uintptr)(p) = v 17 // advance buffer 18 *pbuf = buf[unsafe.Sizeof(v):] 19 // return p 20 return uintptr(unsafe.Pointer(&buf[0])) 21 } 22 23 // envptr used to alloc an *uintptr 24 //go:nosplit 25 func envptr(pbuf *[]byte) *uintptr { 26 return (*uintptr)(unsafe.Pointer(envput(pbuf, 0))) 27 } 28 29 //go:nosplit 30 func envdup(pbuf *[]byte, s string) uintptr { 31 buf := *pbuf 32 copy(buf, s) 33 *pbuf = buf[len(s):] 34 return uintptr(unsafe.Pointer(&buf[0])) 35 } 36 37 //go:nosplit 38 func prepareArgs(sp uintptr) { 39 buf := sys.UnsafeBuffer(sp, 256) 40 41 var argc uintptr = 1 42 // put argc slot 43 envput(&buf, argc) 44 arg0 := envptr(&buf) 45 // end of args 46 envput(&buf, 0) 47 48 envTerm := envptr(&buf) 49 envGoDebug := envptr(&buf) 50 putKernelArgs(&buf) 51 // end of env 52 envput(&buf, 0) 53 54 // put auxillary vector 55 envput(&buf, linux.AT_PAGESZ) 56 envput(&buf, sys.PageSize) 57 envput(&buf, linux.AT_NULL) 58 envput(&buf, 0) 59 60 *arg0 = envdup(&buf, "eggos\x00") 61 *envTerm = envdup(&buf, "TERM=xterm\x00") 62 *envGoDebug = envdup(&buf, "GODEBUG=asyncpreemptoff=1\x00") 63 } 64 65 //go:nosplit 66 func putKernelArgs(pbuf *[]byte) uintptr { 67 var cnt uintptr 68 info := multiboot.BootInfo 69 var flag = info.Flags 70 if flag&multiboot.FlagInfoCmdline == 0 { 71 return 0 72 } 73 var pos uintptr = uintptr(info.Cmdline) 74 if pos == 0 { 75 return cnt 76 } 77 78 var arg uintptr 79 for { 80 arg = strtok(&pos) 81 if arg == 0 { 82 break 83 } 84 envput(pbuf, arg) 85 cnt++ 86 } 87 return cnt 88 } 89 90 //go:nosplit 91 func strtok(pos *uintptr) uintptr { 92 addr := *pos 93 94 // skip spaces 95 for { 96 ch := bytedef(addr) 97 if ch == 0 { 98 return 0 99 } 100 if ch != ' ' { 101 break 102 } 103 addr++ 104 } 105 ret := addr 106 // scan util read space and \0 107 for { 108 ch := bytedef(addr) 109 if ch == ' ' { 110 *(*byte)(unsafe.Pointer(addr)) = 0 111 addr++ 112 break 113 } 114 if ch == 0 { 115 break 116 } 117 addr++ 118 } 119 *pos = addr 120 return ret 121 } 122 123 //go:nosplit 124 func bytedef(addr uintptr) byte { 125 return *(*byte)(unsafe.Pointer(addr)) 126 }