codegen.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. package main
  2. import (
  3. "bytes"
  4. "debug/elf"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "os/exec"
  9. "text/template"
  10. )
  11. const kernconfTmpl = `
  12. #include "u.h"
  13. #include "../port/lib.h"
  14. #include "mem.h"
  15. #include "dat.h"
  16. #include "fns.h"
  17. #include "../port/error.h"
  18. #include "io.h"
  19. {{ range .Rootcodes }}
  20. {{ . }}
  21. {{ end }}
  22. {{ range .Config.Dev }}extern Dev {{ . }}devtab;
  23. {{ end }}
  24. Dev *devtab[] = {
  25. {{ range .Config.Dev }}
  26. &{{ . }}devtab,
  27. {{ end }}
  28. nil,
  29. };
  30. {{ range .Config.Link }}extern void {{ . }}link(void);
  31. {{ end }}
  32. void
  33. links(void)
  34. {
  35. {{ range .Rootnames }}addbootfile("{{ . }}", ramfs_{{ . }}_code, ramfs_{{ . }}_len);
  36. {{ end }}
  37. {{ range .Config.Link }}{{ . }}link();
  38. {{ end }}
  39. }
  40. #include "../ip/ip.h"
  41. {{ range .Config.Ip }}extern void {{ . }}init(Fs*);
  42. {{ end }}
  43. void (*ipprotoinit[])(Fs*) = {
  44. {{ range .Config.Ip }} {{ . }}init,
  45. {{ end }}
  46. nil,
  47. };
  48. #include "../port/sd.h"
  49. {{ range .Config.Sd }}extern SDifc {{ . }}ifc;
  50. {{ end }}
  51. SDifc* sdifc[] = {
  52. {{ range .Config.Sd }} &{{ . }}ifc,
  53. {{ end }}
  54. nil,
  55. };
  56. {{ range .Config.Uart }}extern PhysUart {{ . }}physuart;
  57. {{ end }}
  58. PhysUart* physuart[] = {
  59. {{ range .Config.Uart }} &{{ . }}physuart,
  60. {{ end }}
  61. nil,
  62. };`
  63. const vgaconfTmpl = `
  64. #define Image IMAGE
  65. #include <draw.h>
  66. #include <memdraw.h>
  67. #include <cursor.h>
  68. #include "screen.h"
  69. {{ range .Config.VGA }}extern VGAdev {{ . }}dev;
  70. {{ end }}
  71. VGAdev* vgadev[] = {
  72. {{ range .Config.VGA }} &{{ . }}dev,
  73. {{ end }}
  74. nil,
  75. };
  76. {{ range .Config.VGA }}extern VGAcur {{ . }}cur;
  77. {{ end }}
  78. VGAcur* vgacur[] = {
  79. {{ range .Config.VGA }} &{{ . }}cur,
  80. {{ end }}
  81. nil,
  82. };
  83. Physseg physseg[8] = {
  84. {
  85. .attr = SG_SHARED,
  86. .name = "shared",
  87. .size = SEGMAXPG,
  88. },
  89. {
  90. .attr = SG_BSS,
  91. .name = "memory",
  92. .size = SEGMAXPG,
  93. },
  94. };
  95. int nphysseg = 8;
  96. {{ range .Config.Code }}{{ . }}
  97. {{ end }}
  98. char* conffile = "{{ .Path }}";
  99. `
  100. // These are the two big code generation functions.
  101. // data2c takes the file at path and creates a C byte array containing it.
  102. func data2c(name string, path string) string {
  103. var out []byte
  104. var in []byte
  105. if elf, err := elf.Open(path); err == nil {
  106. elf.Close()
  107. cwd, err := os.Getwd()
  108. tmpf, err := ioutil.TempFile(cwd, name)
  109. failOn(err)
  110. run(nil, *shellhack, exec.Command(tools["strip"], "-o", tmpf.Name(), path))
  111. in, err = ioutil.ReadAll(tmpf)
  112. failOn(err)
  113. tmpf.Close()
  114. os.Remove(tmpf.Name())
  115. } else {
  116. var file *os.File
  117. var err error
  118. file, err = os.Open(path)
  119. failOn(err)
  120. in, err = ioutil.ReadAll(file)
  121. failOn(err)
  122. file.Close()
  123. }
  124. total := len(in)
  125. out = []byte(fmt.Sprintf("static unsigned char ramfs_%s_code[] = {\n", name))
  126. for len(in) > 0 {
  127. for j := 0; j < 16 && len(in) > 0; j++ {
  128. out = append(out, []byte(fmt.Sprintf("0x%02x, ", in[0]))...)
  129. in = in[1:]
  130. }
  131. out = append(out, '\n')
  132. }
  133. out = append(out, []byte(fmt.Sprintf("0,\n};\nint ramfs_%s_len = %v;\n", name, total))...)
  134. return string(out)
  135. }
  136. // confcode creates a kernel configuration header.
  137. func confcode(path string, kern *kernel) []byte {
  138. var rootcodes []string
  139. var rootnames []string
  140. for name, path := range kern.Ramfiles {
  141. code := data2c(name, fromRoot(path))
  142. rootcodes = append(rootcodes, code)
  143. rootnames = append(rootnames, name)
  144. }
  145. vars := struct {
  146. Path string
  147. Config kernconfig
  148. Rootnames []string
  149. Rootcodes []string
  150. }{
  151. path,
  152. kern.Config,
  153. rootnames,
  154. rootcodes,
  155. }
  156. tmpl := template.Must(template.New("kernconf").Parse(kernconfTmpl))
  157. codebuf := &bytes.Buffer{}
  158. failOn(tmpl.Execute(codebuf, vars))
  159. fmt.Printf("VGA IS %v len %d\n", vars.Config.VGA, len(vars.Config.VGA))
  160. if len(vars.Config.VGA) > 0 {
  161. tmpl = template.Must(template.New("vgaconf").Parse(vgaconfTmpl))
  162. vgabuf := &bytes.Buffer{}
  163. failOn(tmpl.Execute(codebuf, vars))
  164. codebuf.Write(vgabuf.Bytes())
  165. }
  166. return codebuf.Bytes()
  167. }