lib.sh 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. # SPDX-License-Identifier: GPL-3.0-only
  2. # Copyright (c) 2022 Caleb La Grange <thonkpeasant@protonmail.com>
  3. # Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
  4. # Copyright (c) 2020-2025 Leah Rowe <leah@libreboot.org>
  5. export LC_COLLATE=C
  6. export LC_ALL=C
  7. _ua="Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0"
  8. ifdtool="elf/ifdtool/default/ifdtool"
  9. cbfstool="elf/cbfstool/default/cbfstool"
  10. rmodtool="elf/cbfstool/default/rmodtool"
  11. tmpgit="$PWD/tmp/gitclone"
  12. grubdata="config/data/grub"
  13. err="err_"
  14. err_()
  15. {
  16. printf "ERROR %s: %s\n" "$0" "$1" 1>&2; exit 1
  17. }
  18. setvars()
  19. {
  20. _setvars="" && [ $# -lt 2 ] && $err "setvars: too few arguments"
  21. val="$1" && shift 1 && for var in "$@"; do
  22. _setvars="$var=\"$val\"; $_setvars"
  23. done; printf "%s\n" "${_setvars% }"
  24. }
  25. chkvars()
  26. {
  27. for var in "$@"; do
  28. eval "[ -n \"\${$var+x}\" ] || \$err \"$var unset\""
  29. eval "[ -n \"\$$var\" ] || \$err \"$var unset\""
  30. done; return 0
  31. }
  32. eval "`setvars "" _nogit board reinstall versiondate projectsite projectname \
  33. aur_notice configdir datadir version relname xbmk_parent`"
  34. for fv in projectname projectsite version versiondate; do
  35. eval "[ ! -f \"$fv\" ] || read -r $fv < \"$fv\" || :"
  36. done; chkvars projectname projectsite
  37. setcfg()
  38. {
  39. [ $# -gt 1 ] && printf "e \"%s\" f missing && return %s;\n" "$1" "$2"
  40. [ $# -gt 1 ] || \
  41. printf "e \"%s\" f not && %s \"Missing config\";\n" "$1" "$err"
  42. printf ". \"%s\" || %s \"Could not read config\";\n" "$1" "$err"
  43. }
  44. e()
  45. {
  46. es_t="e" && [ $# -gt 1 ] && es_t="$2"
  47. es2="already exists"
  48. estr="[ -$es_t \"\$1\" ] || return 1"
  49. [ $# -gt 2 ] && estr="[ -$es_t \"\$1\" ] && return 1" && es2="missing"
  50. eval "$estr"; printf "%s %s\n" "$1" "$es2" 1>&2
  51. }
  52. install_packages()
  53. {
  54. [ $# -lt 2 ] && $err "fewer than two arguments"
  55. [ $# -gt 2 ] && reinstall="$3"
  56. eval "`setcfg "config/dependencies/$2"`"
  57. chkvars pkg_add pkglist
  58. $pkg_add $pkglist || $err "Cannot install packages"
  59. [ -n "$aur_notice" ] && \
  60. printf "You need AUR packages: %s\n" "$aur_notice" 1>&2; :
  61. }
  62. if [ $# -gt 0 ] && [ "$1" = "dependencies" ]; then
  63. install_packages "$@" || exit 1
  64. exit 0
  65. fi
  66. pyver="2"
  67. python="python3"
  68. command -v python3 1>/dev/null || python="python"
  69. command -v $python 1>/dev/null || pyver=""
  70. [ -z "$pyver" ] || \
  71. python -c 'import sys; print(sys.version_info[:])' 1>/dev/null \
  72. 2>/dev/null || $err "Cannot determine which Python version."
  73. [ -n "$pyver" ] && \
  74. pyver="`python -c 'import sys; print(sys.version_info[:])' | \
  75. awk '{print $1}'`" && \
  76. pyver="${pyver#(}" && pyver="${pyver%,}"
  77. if [ "${pyver%%.*}" != "3" ]; then
  78. printf "Wrong python version, or python missing. Must be v 3.x.\n" 1>&2
  79. exit 1
  80. fi
  81. id -u 1>/dev/null 2>/dev/null || $err "suid check failed (id -u)"
  82. [ "$(id -u)" != "0" ] || $err "this command as root is not permitted"
  83. # XBMK_CACHE is a directory, for caching downloads and git repositories
  84. [ -z "${XBMK_CACHE+x}" ] && export XBMK_CACHE="$PWD/cache"
  85. [ -z "$XBMK_CACHE" ] && export XBMK_CACHE="$PWD/cache"
  86. [ -L "$XBMK_CACHE" ] && [ "$XBMK_CACHE" = "$PWD/cache" ] && \
  87. $err "cachedir is default, $PWD/cache, but it exists and is a symlink"
  88. [ -L "$XBMK_CACHE" ] && export XBMK_CACHE="$PWD/cache"
  89. [ -f "$XBMK_CACHE" ] && $err "cachedir '$XBMK_CACHE' exists but it's a file"
  90. # unify all temporary files/directories in a single TMPDIR
  91. [ -z "${TMPDIR+x}" ] || [ "${TMPDIR%_*}" = "/tmp/xbmk" ] || unset TMPDIR
  92. [ -n "${TMPDIR+x}" ] && export TMPDIR="$TMPDIR"
  93. if [ -z "${TMPDIR+x}" ]; then
  94. [ -f "lock" ] && $err "$PWD/lock exists. Is a build running?"
  95. export TMPDIR="/tmp"
  96. export TMPDIR="$(mktemp -d -t xbmk_XXXXXXXX)"
  97. touch lock || $err "cannot create 'lock' file"
  98. rm -Rf "$XBMK_CACHE/xbmkpath" "$XBMK_CACHE/gnupath" || \
  99. $err "cannot remove xbmkpath"
  100. mkdir -p "$XBMK_CACHE/gnupath" "$XBMK_CACHE/xbmkpath" || \
  101. $err "cannot create gnupath"
  102. export PATH="$XBMK_CACHE/xbmkpath:$XBMK_CACHE/gnupath:$PATH" || \
  103. $err "Can't create gnupath/xbmkpath"
  104. (
  105. # set up python v3.x in PATH, in case it's not set up correctly.
  106. # see code above that detected the correct python3 command.
  107. cd "$XBMK_CACHE/xbmkpath" || $err "can't cd $XBMK_CACHE/xbmkpath"
  108. ln -s "`command -v "$python"`" python || \
  109. $err "Can't set up python symlink in $XBMK_CACHE/xbmkpath"
  110. ) || $err "Can't set up python symlink in $XBMK_CACHE/xbmkpath"
  111. xbmk_parent="y"
  112. fi
  113. # if "y": a coreboot target won't be built if target.cfg says release="n"
  114. # (this is used to exclude certain build targets from releases)
  115. [ -z "${XBMK_RELEASE+x}" ] && export XBMK_RELEASE="n"
  116. [ "$XBMK_RELEASE" = "y" ] || export XBMK_RELEASE="n"
  117. [ -z "${XBMK_THREADS+x}" ] && export XBMK_THREADS=1
  118. expr "X$XBMK_THREADS" : "X-\{0,1\}[0123456789][0123456789]*$" \
  119. 1>/dev/null 2>/dev/null || export XBMK_THREADS=1 # user gave a non-integer
  120. x_() {
  121. [ $# -lt 1 ] || "$@" || \
  122. $err "Unhandled non-zero exit: $(echo "$@")"; return 0
  123. }
  124. [ -e ".git" ] || [ -f "version" ] || printf "unknown\n" > version || \
  125. $err "Cannot generate unknown version file"
  126. [ -e ".git" ] || [ -f "versiondate" ] || printf "1716415872\n" > versiondate \
  127. || $err "Cannot generate unknown versiondate file"
  128. version_="$version"
  129. [ ! -e ".git" ] || version="$(git describe --tags HEAD 2>&1)" || \
  130. version="git-$(git rev-parse HEAD 2>&1)" || version="$version_"
  131. versiondate_="$versiondate"
  132. [ ! -e ".git" ] || versiondate="$(git show --no-patch --no-notes \
  133. --pretty='%ct' HEAD)" || versiondate="$versiondate_"
  134. for p in projectname version versiondate projectsite; do
  135. chkvars "$p"; eval "x_ printf \"%s\\n\" \"\$$p\" > $p"
  136. done
  137. relname="$projectname-$version"
  138. export LOCALVERSION="-$projectname-${version%%-*}"
  139. check_defconfig()
  140. {
  141. [ -d "$1" ] || $err "Target '$1' not defined."
  142. for x in "$1"/config/*; do
  143. [ -f "$x" ] && printf "%s\n" "$x" && return 1
  144. done; return 0
  145. }
  146. remkdir()
  147. {
  148. rm -Rf "$1" || $err "remkdir: !rm -Rf \"$1\""
  149. mkdir -p "$1" || $err "remkdir: !mkdir -p \"$1\""
  150. }
  151. mkrom_tarball()
  152. {
  153. printf "%s\n" "$version" > "$1/version" || $err "$1 !version"
  154. printf "%s\n" "$versiondate" > "$1/versiondate" || $err "$1 !vdate"
  155. printf "%s\n" "$projectname" > "$1/projectname" || $err "$1 !pname"
  156. mktarball "$1" "${1%/*}/${relname}_${1##*/}.tar.xz"; x_ rm -Rf "$1"; :
  157. }
  158. mktarball()
  159. {
  160. if [ "${2%/*}" != "$2" ]; then
  161. mkdir -p "${2%/*}" || $err "mk, !mkdir -p \"${2%/*}\""
  162. fi
  163. tar -c "$1" | xz -T$XBMK_THREADS -9e > "$2" || $err "mktarball 2, $1"
  164. }
  165. mksha512sum()
  166. {
  167. (
  168. [ "${1%/*}" != "$1" ] && x_ cd "${1%/*}"
  169. sha512sum ./"${1##*/}" >> "$2" || $err "!sha512sum \"$1\" > \"$2\""
  170. ) || $err "failed to create tarball checksum"
  171. }
  172. rmgit()
  173. {
  174. (
  175. cd "$1" || $err "!cd gitrepo $1"
  176. find . -name ".git" -exec rm -Rf {} + || $err "!rm .git $1"
  177. find . -name ".gitmodules" -exec rm -Rf {} + || $err "!rm .gitmod $1"
  178. ) || $err "Cannot remove .git/.gitmodules in $1"
  179. }
  180. # return 0 if project is single-tree, otherwise 1
  181. # e.g. coreboot is multi-tree, so 1
  182. singletree()
  183. {
  184. for targetfile in "config/${1}/"*/target.cfg; do
  185. [ -e "$targetfile" ] && [ -f "$targetfile" ] && return 1; :
  186. done; return 0
  187. }
  188. # can grab from the internet, or copy locally.
  189. # if copying locally, it can only copy a file.
  190. download()
  191. {
  192. _dlop="curl" && [ $# -gt 4 ] && _dlop="$5"
  193. cached="$XBMK_CACHE/file/$4"
  194. dl_fail="n" # 1 url, 2 url backup, 3 destination, 4 checksum
  195. vendor_checksum "$4" "$cached" 2>/dev/null && dl_fail="y"
  196. [ "$dl_fail" = "n" ] && e "$3" f && return 0
  197. mkdir -p "${3%/*}" "$XBMK_CACHE/file" || \
  198. $err "!mkdir '$3' '$XBMK_CACHE/file'"
  199. for url in "$1" "$2"; do
  200. [ "$dl_fail" = "n" ] && break
  201. [ -z "$url" ] && continue
  202. rm -f "$cached" || $err "!rm -f '$cached'"
  203. if [ "$_dlop" = "curl" ]; then
  204. curl --location --retry 3 -A "$_ua" "$url" \
  205. -o "$cached" || wget --tries 3 -U "$_ua" "$url" \
  206. -O "$cached" || continue
  207. elif [ "$_dlop" = "copy" ]; then
  208. [ -L "$url" ] && \
  209. printf "dl %s %s %s %s: '%s' is a symlink\n" \
  210. "$1" "$2" "$3" "$4" "$url" 1>&2 && continue
  211. [ ! -f "$url" ] && \
  212. printf "dl %s %s %s %s: '%s' not a file\n" \
  213. "$1" "$2" "$3" "$4" "$url" 1>&2 && continue
  214. cp "$url" "$cached" || continue
  215. else
  216. $err "$1 $2 $3 $4: Unsupported dlop type: '$_dlop'"
  217. fi
  218. vendor_checksum "$4" "$cached" || dl_fail="n"
  219. done; [ "$dl_fail" = "y" ] && $err "$1 $2 $3 $4: not downloaded"
  220. [ "$cached" = "$3" ] || cp "$cached" "$3" || $err "!d cp $cached $3"; :
  221. }
  222. vendor_checksum()
  223. {
  224. [ "$(sha512sum "$2" | awk '{print $1}')" != "$1" ] || return 1
  225. printf "Bad checksum for file: %s\n" "$2" 1>&2; rm -f "$2" || :; :
  226. }
  227. cbfs()
  228. {
  229. fRom="$1" # image to operate on
  230. fAdd="$2" # file to add
  231. fName="$3" # filename when added in CBFS
  232. ccmd="add-payload" && [ $# -gt 3 ] && [ $# -lt 5 ] && ccmd="add"
  233. lzma="-c lzma" && [ $# -gt 3 ] && [ $# -lt 5 ] && lzma="-t $4"
  234. # hack. TODO: do it better. this whole function is cursed
  235. if [ $# -gt 4 ]; then
  236. # add flat binary for U-Boot (u-boot.bin) on x86
  237. if [ "$5" = "0x1110000" ]; then
  238. ccmd="add-flat-binary"
  239. lzma="-c lzma -l 0x1110000 -e 0x1110000"
  240. fi
  241. fi
  242. "$cbfstool" "$fRom" $ccmd -f "$fAdd" -n "$fName" $lzma || \
  243. $err "CBFS fail: $fRom $ccmd -f '$fAdd' -n '$fName' $lzma"; :
  244. }
  245. mk()
  246. {
  247. mk_flag="$1" || $err "No argument given"
  248. shift 1 && for mk_arg in "$@"; do
  249. ./mk $mk_flag $mk_arg || $err "./mk $mk_flag $mk_arg"; :
  250. done; :
  251. }