1 # Copyright 2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: kernel-install.eclass
6 # Distribution Kernel Project <dist-kernel@gentoo.org>
8 # Michał Górny <mgorny@gentoo.org>
10 # @BLURB: Installation mechanics for Distribution Kernels
12 # This eclass provides the logic needed to test and install different
13 # kinds of Distribution Kernel packages, including both kernels built
14 # from source and distributed as binaries. The eclass relies on the
15 # ebuild installing a subset of built kernel tree into
16 # /usr/src/linux-${PV} containing the kernel image in its standard
17 # location and System.map.
19 # The eclass exports src_test, pkg_postinst and pkg_postrm.
20 # Additionally, the inherited mount-boot eclass exports pkg_pretend.
21 # It also stubs out pkg_preinst and pkg_prerm defined by mount-boot.
23 if [[ ! ${_KERNEL_INSTALL_ECLASS} ]]; then
27 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
32 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
42 https://dev.gentoo.org/~mgorny/dist/tinycorelinux-${TCL_VER}-amd64.qcow2
45 https://dev.gentoo.org/~mgorny/dist/tinycorelinux-${TCL_VER}-x86.qcow2
50 IUSE="+initramfs test"
51 RESTRICT+=" !test? ( test ) test? ( userpriv )"
53 # install-DEPEND actually
54 # note: we need installkernel with initramfs support!
57 sys-kernel/installkernel-gentoo
58 sys-kernel/installkernel-systemd-boot
60 initramfs? ( >=sys-kernel/dracut-049-r3 )"
65 amd64? ( app-emulation/qemu[qemu_softmmu_targets_x86_64] )
66 x86? ( app-emulation/qemu[qemu_softmmu_targets_i386] )
69 # @FUNCTION: kernel-install_build_initramfs
70 # @USAGE: <output> <version>
72 # Build an initramfs for the kernel. <output> specifies the absolute
73 # path where initramfs will be created, while <version> specifies
74 # the kernel version, used to find modules.
75 kernel-install_build_initramfs() {
76 debug-print-function ${FUNCNAME} "${@}"
78 [[ ${#} -eq 2 ]] || die "${FUNCNAME}: invalid arguments"
82 ebegin "Building initramfs via dracut"
83 dracut --force "${output}" "${version}"
84 eend ${?} || die "Building initramfs failed"
87 # @FUNCTION: kernel-install_get_image_path
89 # Get relative kernel image path specific to the current ${ARCH}.
90 kernel-install_get_image_path() {
93 echo arch/x86/boot/bzImage
96 die "${FUNCNAME}: unsupported ARCH=${ARCH}"
101 # @FUNCTION: kernel-install_install_kernel
102 # @USAGE: <version> <image> <system.map>
104 # Install kernel using installkernel tool. <version> specifies
105 # the kernel version, <image> full path to the image, <system.map>
106 # full path to System.map.
107 kernel-install_install_kernel() {
108 debug-print-function ${FUNCNAME} "${@}"
110 [[ ${#} -eq 3 ]] || die "${FUNCNAME}: invalid arguments"
115 ebegin "Installing the kernel via installkernel"
116 # note: .config is taken relatively to System.map;
117 # initrd relatively to bzImage
118 installkernel "${version}" "${image}" "${map}"
119 eend ${?} || die "Installing the kernel failed"
122 # @FUNCTION: kernel-install_update_symlink
123 # @USAGE: <target> <version>
125 # Update the kernel source symlink at <target> (full path) with a link
126 # to <target>-<version> if it's either missing or pointing out to
127 # an older version of this package.
128 kernel-install_update_symlink() {
129 debug-print-function ${FUNCNAME} "${@}"
131 [[ ${#} -eq 2 ]] || die "${FUNCNAME}: invalid arguments"
135 if [[ ! -e ${target} ]]; then
136 ebegin "Creating ${target} symlink"
137 ln -f -n -s "${target##*/}-${version}" "${target}"
140 local symlink_target=$(readlink "${target}")
141 local symlink_ver=${symlink_target#${target##*/}-}
142 if [[ ${symlink_target} == ${target##*/}-* && \
143 -z ${symlink_ver//[0-9.]/} ]]
145 local symlink_pkg=${CATEGORY}/${PN}-${symlink_ver}
146 # if the current target is either being replaced, or still
147 # installed (probably depclean candidate), update the symlink
148 if has "${symlink_ver}" ${REPLACING_VERSIONS} ||
149 has_version -r "~${symlink_pkg}"
151 ebegin "Updating ${target} symlink"
152 ln -f -n -s "${target##*/}-${version}" "${target}"
159 # @FUNCTION: kernel-install_get_qemu_arch
161 # Get appropriate qemu suffix for the current ${ARCH}.
162 kernel-install_get_qemu_arch() {
163 debug-print-function ${FUNCNAME} "${@}"
173 die "${FUNCNAME}: unsupported ARCH=${ARCH}"
178 # @FUNCTION: kernel-install_test
179 # @USAGE: <version> <image> <modules>
181 # Test that the kernel can successfully boot a minimal system image
182 # in qemu. <version> is the kernel version, <image> path to the image,
183 # <modules> path to module tree.
184 kernel-install_test() {
185 debug-print-function ${FUNCNAME} "${@}"
187 [[ ${#} -eq 3 ]] || die "${FUNCNAME}: invalid arguments"
192 local qemu_arch=$(kernel-install_get_qemu_arch)
196 --confdir /dev/null \
198 --kmoddir "${modules}" \
199 "${T}/initrd" "${version}" || die
200 # get a read-write copy of the disk image
201 cp "${DISTDIR}/tinycorelinux-${TCL_VER}-${ARCH}.qcow2" \
202 "${T}/fs.qcow2" || die
205 cat > run.sh <<-EOF || die
207 exec qemu-system-${qemu_arch} \
212 -initrd '${T}/initrd' \
214 -hda '${T}/fs.qcow2' \
215 -append 'root=/dev/sda console=ttyS0,115200n8'
217 chmod +x run.sh || die
218 # TODO: initramfs does not let core finish starting on some systems,
219 # figure out how to make it better at that
220 expect - <<-EOF || die "Booting kernel failed"
225 send_error "\n* Kernel panic"
228 "Entering emergency mode" {
229 send_error "\n* Initramfs failed to start the system"
233 send_error "\n* Booted successfully"
237 send_error "\n* Kernel boot timed out"
244 # @FUNCTION: kernel-install_src_test
246 # Boilerplate function to remind people to call the tests.
247 kernel-install_src_test() {
248 debug-print-function ${FUNCNAME} "${@}"
250 die "Please redefine src_test() and call kernel-install_test()."
253 # @FUNCTION: kernel-install_pkg_preinst
255 # Stub out mount-boot.eclass.
256 kernel-install_pkg_preinst() {
257 debug-print-function ${FUNCNAME} "${@}"
262 # @FUNCTION: kernel-install_pkg_postinst
264 # Build an initramfs for the kernel, install it and update
265 # the /usr/src/linux symlink.
266 kernel-install_pkg_postinst() {
267 debug-print-function ${FUNCNAME} "${@}"
269 if [[ -z ${ROOT} ]]; then
270 mount-boot_pkg_preinst
272 local image_path=$(kernel-install_get_image_path)
273 if use initramfs; then
274 # putting it alongside kernel image as 'initrd' makes
275 # kernel-install happier
276 kernel-install_build_initramfs \
277 "${EROOT}/usr/src/linux-${PV}/${image_path%/*}/initrd" \
281 kernel-install_install_kernel "${PV}" \
282 "${EROOT}/usr/src/linux-${PV}/${image_path}" \
283 "${EROOT}/usr/src/linux-${PV}/System.map"
286 kernel-install_update_symlink "${EROOT}/usr/src/linux" "${PV}"
289 # @FUNCTION: kernel-install_pkg_prerm
291 # Stub out mount-boot.eclass.
292 kernel-install_pkg_prerm() {
293 debug-print-function ${FUNCNAME} "${@}"
298 # @FUNCTION: kernel-install_pkg_postrm
300 # No-op at the moment. Will be used to remove obsolete kernels
302 kernel-install_pkg_postrm() {
303 debug-print-function ${FUNCNAME} "${@}"
305 if [[ -z ${ROOT} ]] && use initramfs; then
306 local image_path=$(kernel-install_get_image_path)
307 ebegin "Removing initramfs"
308 rm -f "${EROOT}/usr/src/linux-${PV}/${image_path%/*}/initrd" &&
309 find "${EROOT}/usr/src/linux-${PV}" -depth -type d -empty -delete
314 _KERNEL_INSTALL_ECLASS=1
317 EXPORT_FUNCTIONS src_test pkg_preinst pkg_postinst pkg_prerm pkg_postrm