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  }