grub.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package grub
  15. import (
  16. "fmt"
  17. "strings"
  18. )
  19. func GetYunionOSConfig(sleepTime int, httpSite, kernel string, kernelArgs string, initrd string, useTftpDownload bool) string {
  20. if useTftpDownload {
  21. site := strings.Split(httpSite, ":")[0]
  22. kernel = fmt.Sprintf("(tftp,%s)/%s", site, kernel)
  23. initrd = fmt.Sprintf("(tftp,%s)/%s", site, initrd)
  24. } else {
  25. kernel = fmt.Sprintf("(http,%s)/tftp/%s", httpSite, kernel)
  26. initrd = fmt.Sprintf("(http,%s)/tftp/%s", httpSite, initrd)
  27. }
  28. return fmt.Sprintf(`
  29. set timeout=%d
  30. menuentry 'YunionOS for PXE' --class os {
  31. echo "Loading linux %s ..."
  32. linux %s %s
  33. echo "Loading initrd %s ..."
  34. initrd %s
  35. }
  36. `, sleepTime, kernel, kernel, kernelArgs, initrd, initrd)
  37. }
  38. var (
  39. BOOT_EFI_MATCHER = "(hd*,gpt*)/EFI/BOOT/BOOTX64.EFI (hd*,msdos*)/EFI/BOOT/BOOTX64.EFI (hd*,gpt*)/EFI/BOOT/BOOTAA64.EFI (hd*,msdos*)/EFI/BOOT/BOOTAA64.EFI"
  40. GRUB_EFI_MATCHER = "(md*)/EFI/*/shimx64.efi (md*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimx64.efi (hd*,msdos*)/EFI/*/shimx64.efi (hd*,gpt*)/EFI/*/grubx64.efi (hd*,msdos*)/EFI/*/grubx64.efi (hd*,gpt*)/EFI/*/shimaa64.efi (hd*,msdos*)/EFI/*/shimaa64.efi (hd*,gpt*)/EFI/*/grubaa64.efi (hd*,msdos*)/EFI/*/grubaa64.efi"
  41. GRUB_CFG_MATCHER = "(md*)/boot/*/grub.cfg (md*)/*/grub.cfg (md*)/grub.cfg (md*)/EFI/*/grub.cfg (md*)/EFI/*/*/grub.cfg (hd*,gpt*)/boot/*/grub.cfg (hd*,gpt*)/*/grub.cfg (hd*,gpt*)/grub.cfg (hd*,gpt*)/EFI/*/grub.cfg (hd*,gpt*)/EFI/*/*/grub.cfg (hd*,msdos*)/boot/*/grub.cfg (hd*,msdos*)/*/grub.cfg (hd*,msdos*)/grub.cfg (hd*,msdos*)/EFI/*/grub.cfg (hd*,msdos*)/EFI/*/*/grub.cfg"
  42. )
  43. // REF: https://github.com/bluebanquise/infrastructure/blob/master/packages/bluebanquise-ipxe/grub2-efi-autofind.cfg
  44. const autoFindCfg = `
  45. echo "Loading modules..."
  46. insmod part_gpt
  47. insmod fat
  48. insmod chain
  49. insmod part_msdos
  50. insmod ext2
  51. insmod regexp
  52. insmod xfs
  53. insmod mdraid1x
  54. insmod mdraid09
  55. echo
  56. echo "======================= lsmod ======================================="
  57. lsmod
  58. echo
  59. echo "======================= devices ====================================="
  60. ls
  61. echo
  62. echo "======================= Searching for the BOOT EFI executable ======="
  63. echo "Scanning, 1st pass"
  64. for efi in %s; do
  65. regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
  66. echo "- Scanning: $efi"
  67. if [ -e "$efi" ] ; then
  68. echo " Found: $efi"
  69. else
  70. echo " $efi does not exist"
  71. fi
  72. done
  73. echo
  74. echo "Scanning, 2nd pass..."
  75. for efi in %s; do
  76. echo "- Scanning: $efi"
  77. if [ -e "$efi" ] ; then
  78. regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
  79. echo " Found: $efi"
  80. echo " Root: $root"
  81. echo " Chainloading $efi"
  82. chainloader "$efi"
  83. boot
  84. fi
  85. done
  86. echo
  87. echo " Found no BOOT EFI executable. Falling back to shell..."
  88. echo
  89. echo "======================= Searching for Grub EFI executables =========="
  90. echo "Scanning, 1st pass"
  91. for efi in %s ; do
  92. regexp --set=1:root '^\(([^)]+)\)/' "${efi}"
  93. echo "- Scanning: $efi"
  94. if [ -e "$efi" ] ; then
  95. echo " Found: $efi"
  96. else
  97. echo " $efi does not exist"
  98. fi
  99. done
  100. echo
  101. echo "Scanning, 2nd pass..."
  102. for efi in %s ; do
  103. echo "- Scanning: $efi"
  104. if [ -e "$efi" ] ; then
  105. regexp --set 1:root '^\(([^)]+)\)/' "${efi}"
  106. echo " Found: $efi"
  107. echo " Root: $root"
  108. echo " Chainloading $efi"
  109. chainloader "$efi"
  110. boot
  111. fi
  112. done
  113. echo
  114. echo " Found no Grub EFI executable to load an OS."
  115. echo
  116. echo "======================= Searching for grub.cfg on local disks ======="
  117. echo "Scanning, 1st pass..."
  118. for grubcfg in %s ; do
  119. regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
  120. if [ -e "$grubcfg" ] ; then
  121. echo " Found: $grubcfg"
  122. else
  123. echo " $grubcfg does not exist"
  124. fi
  125. done
  126. echo
  127. echo "Scanning, 2nd pass..."
  128. for grubcfg in %s ; do
  129. echo "- Scanning: $grubcfg"
  130. if [ -e "${grubcfg}" ]; then
  131. regexp --set=1:root '^\(([^)]+)\)/' "${grubcfg}"
  132. echo " Found: $grubcfg"
  133. echo " Root: $root"
  134. # echo " Contents:"
  135. # cat "$grubcfg"
  136. configfile "${grubcfg}"
  137. boot
  138. fi
  139. done
  140. echo
  141. echo " Found no grub.cfg configuration file to load."
  142. sleep 4s
  143. `
  144. func GetAutoFindConfig() string {
  145. return fmt.Sprintf(autoFindCfg, BOOT_EFI_MATCHER, BOOT_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_EFI_MATCHER, GRUB_CFG_MATCHER, GRUB_CFG_MATCHER)
  146. }
  147. // REF: https://archived.forum.manjaro.org/t/detecting-efi-files-and-booting-them-from-grub/38083
  148. const efiDetectMenuCfg = `
  149. menuentry "Detect EFI bootloaders " {
  150. insmod part_gpt
  151. insmod fat
  152. insmod chain
  153. insmod part_msdos
  154. insmod ext2
  155. insmod xfs
  156. for efi in (*,gpt*)/efi/*/*.efi (*,gpt*)/efi/*/*/*.efi (*,gpt*)/*.efi (*,gpt*)/*/*.efi; do
  157. regexp --set=1:efi_device '^\((.*)\)/' "${efi}"
  158. if [ -e "${efi}" ]; then
  159. efi_found=true
  160. menuentry --class=efi "${efi}" "${efi_device}" {
  161. root="${2}"
  162. chainloader "${1}"
  163. }
  164. fi
  165. done
  166. if [ "${efi_found}" != true ]; then
  167. menuentry --hotkey=q --class=find.none "No EFI files detected." {menu_reload}
  168. else
  169. menuentry --hotkey=q --class=cancel "Cancel" {menu_reload}
  170. fi
  171. }
  172. `
  173. func GetEFIDetectMenuConfig() string {
  174. return efiDetectMenuCfg
  175. }