├── .github └── workflows │ ├── shellcheck.yml │ └── test.yml ├── COPYING ├── Dockerfile ├── LICENSE ├── README.md ├── grub └── 05_uki ├── hooks ├── 30-emerge-kernel-module-rebuild.install ├── 50-dracut.install ├── 60-ukify.install ├── 91-grub-mkconfig.install ├── 95-efistub-uefi-mkconfig.install ├── 95-refind-copy-icon.install ├── 99-check-diskspace.install ├── 99-write-log.install └── systemd │ ├── 00-00machineid-directory.install │ ├── 10-copy-prebuilt.install │ ├── 30-emerge-kernel-module-rebuild.install │ ├── 85-check-diskspace.install │ ├── 90-compat.install │ ├── 90-zz-update-static.install │ ├── 91-grub-mkconfig.install │ ├── 95-efistub-kernel-bootcfg.install │ ├── 95-refind-copy-icon.install │ └── 99-write-log.install ├── installkernel ├── installkernel-9999.ebuild ├── installkernel.8 ├── installkernel.logrotate ├── run_tests.sh └── run_tests_in_docker.sh /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | name: Test installkernel 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | 8 | jobs: 9 | shellcheck: 10 | name: Shellcheck 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Run ShellCheck 15 | uses: ludeeus/action-shellcheck@master 16 | with: 17 | additional_files: '*.install' 18 | 19 | 20 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test installkernel 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - name: Run tests 14 | run: ./run_tests_in_docker.sh 15 | 16 | 17 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | This script was extracted from debianutils. It was subsequenly modified 2 | for Gentoo by Michał Górny and Nowa Ammerlaan. 3 | 4 | [excerpt from debian/copyright] 5 | 6 | This is the Debian GNU/Linux package debianutils. 7 | 8 | It is an original Debian package. Programs in it were maintained by 9 | Guy Maor , and are now maintained by Clint Adams 10 | . 11 | 12 | All its programs except savelog, and which may be 13 | redistributed under the terms of the GNU GPL, Version 2 or later, 14 | found on Debian systems in the file /usr/share/common-licenses/GPL. 15 | 16 | which is in the public domain. 17 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gentoo/stage3:amd64-systemd 2 | 3 | RUN wget --progress=dot:mega -O - https://github.com/gentoo-mirror/gentoo/archive/master.tar.gz | tar -xz \ 4 | && mv gentoo-master /var/db/repos/gentoo 5 | RUN echo -e "ACCEPT_KEYWORDS=\"~amd64\"\nACCEPT_LICENSE=\"*\"\nFEATURES=\"-news -sandbox -usersandbox -cgroup binpkg-multi-instance -binpkg-docompress -binpkg-dostrip parallel-install -ipc-sandbox -network-sandbox -pid-sandbox binpkg-ignore-signature buildpkg getbinpkg\"\nMAKEOPTS=\"--jobs=$(nproc) --load-average=$(nproc)\"\nUSE=\"-initramfs kernel-install boot ukify -bash dash\"" >> /etc/portage/make.conf 6 | RUN echo -e "sys-kernel/installkernel systemd -dracut -grub -systemd-boot -uki -ukify" >> /etc/portage/package.use/installkernel 7 | RUN emerge --jobs="$(nproc)" --load-average="$(nproc)" sys-kernel/gentoo-kernel-bin app-text/tree sys-apps/systemd sys-kernel/dracut sys-boot/grub sys-kernel/installkernel sys-fs/dosfstools sys-boot/refind app-alternatives/sh 8 | 9 | CMD /tmp/installkernel-gentoo-9999/run_tests.sh 10 | 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # installkernel-gentoo 2 | 3 | Install the kernel on a Gentoo Linux system. 4 | 5 | This script is called by the kernel's `make install` if it is installed as 6 | `/sbin/installkernel`. It is also called by `kernel-install.eclass`. 7 | 8 | This script was extracted from `sys-apps/debianutils`. It was subsequenly modified 9 | for Gentoo by Michał Górny and Nowa Ammerlaan. 10 | 11 | See the [installkernel Gentoo wiki page](https://wiki.gentoo.org/wiki/Installkernel) for more details. 12 | 13 | ## Making changes 14 | 15 | When making changes: 16 | - Adjust the `installkernel-9999.ebuild` in this repository if changes to the `::gentoo` ebuild are intended, then 17 | - Run tests with `./run_tests_in_docker.sh` (installing Docker is required). 18 | 19 | Do NOT run `./run_tests.sh` outside of any containers, it WILL mess with the systems `/boot` and `/efi`. 20 | -------------------------------------------------------------------------------- /grub/05_uki: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | set -e 3 | 4 | # grub-mkconfig helper script, installed by sys-kernel/installkernel[grub,uki] 5 | # 6 | # Copyright 2025 Gentoo Authors 7 | # Distributed under the terms of the GNU General Public License v3+ 8 | # 9 | # Bug: https://bugs.gentoo.org/942201 10 | 11 | prefix="/usr" 12 | exec_prefix="/usr" 13 | datarootdir="/usr/share" 14 | 15 | . "$pkgdatadir/grub-mkconfig_lib" 16 | 17 | export TEXTDOMAIN=grub 18 | export TEXTDOMAINDIR="${datarootdir}/locale" 19 | 20 | # loop-AES arranges things so that /dev/loop/X can be our root device, but 21 | # the initrds that Linux uses don't like that. 22 | case ${GRUB_DEVICE} in 23 | /dev/loop/*|/dev/loop[0-9]) 24 | GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` 25 | ;; 26 | esac 27 | 28 | : ${GRUB_CMDLINE_LINUX_RECOVERY:=single} 29 | 30 | # Default to disabling partition uuid support to maintian compatibility with 31 | # older kernels. 32 | : ${GRUB_DISABLE_LINUX_PARTUUID=true} 33 | 34 | # btrfs may reside on multiple devices. We cannot pass them as value of root= parameter 35 | # and mounting btrfs requires user space scanning, so force UUID in this case. 36 | if ( [ "x${GRUB_DEVICE_UUID}" = "x" ] && [ "x${GRUB_DEVICE_PARTUUID}" = "x" ] ) \ 37 | || ( [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ 38 | && [ "x${GRUB_DISABLE_LINUX_PARTUUID}" = "xtrue" ] ) \ 39 | || ( ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \ 40 | && ! test -e "/dev/disk/by-partuuid/${GRUB_DEVICE_PARTUUID}" ) \ 41 | || ( test -e "${GRUB_DEVICE}" && uses_abstraction "${GRUB_DEVICE}" lvm ); then 42 | LINUX_ROOT_DEVICE=${GRUB_DEVICE} 43 | elif [ "x${GRUB_DEVICE_UUID}" = "x" ] \ 44 | || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ]; then 45 | LINUX_ROOT_DEVICE=PARTUUID=${GRUB_DEVICE_PARTUUID} 46 | else 47 | LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} 48 | fi 49 | 50 | case x"$GRUB_FS" in 51 | xbtrfs) 52 | rootsubvol="`make_system_path_relative_to_its_root /`" 53 | rootsubvol="${rootsubvol#/}" 54 | if [ "x${rootsubvol}" != x ]; then 55 | GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}" 56 | fi;; 57 | xzfs) 58 | rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true` 59 | bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`" 60 | LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs%/}" 61 | ;; 62 | esac 63 | 64 | title_correction_code= 65 | 66 | linux_entry () 67 | { 68 | os="$1" 69 | version="$2" 70 | type="$3" 71 | args="$4" 72 | 73 | class="--class ${os} --class gnu-linux --class gnu --class os" 74 | 75 | if [ -z "$boot_device_id" ]; then 76 | boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" 77 | fi 78 | if [ x$type != xsimple ] ; then 79 | case $type in 80 | recovery) 81 | title="$(gettext_printf "%s, with UKI %s (recovery mode)" "${os}" "${version}")" ;; 82 | *) 83 | title="$(gettext_printf "%s, with UKI %s" "${os}" "${version}")" ;; 84 | esac 85 | if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then 86 | replacement_title="$(echo "Advanced options for ${os}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')" 87 | quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)" 88 | title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;" 89 | grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")" 90 | fi 91 | echo "menuentry '$(echo "$title" | grub_quote)' ${class} \$menuentry_id_option 'gnulinux-$version-$type-$boot_device_id' {" | sed "s/^/$submenu_indentation/" 92 | else 93 | echo "menuentry '$(echo "$os" | grub_quote)' ${class} \$menuentry_id_option 'gnulinux-simple-$boot_device_id' {" | sed "s/^/$submenu_indentation/" 94 | fi 95 | if [ x$type != xrecovery ] ; then 96 | save_default_entry | grub_add_tab 97 | fi 98 | 99 | # Use ELILO's generic "efifb" when it's known to be available. 100 | # FIXME: We need an interface to select vesafb in case efifb can't be used. 101 | if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then 102 | echo " load_video" | sed "s/^/$submenu_indentation/" 103 | if grep -qx "CONFIG_FB_EFI=y" "${config}" 2> /dev/null \ 104 | && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" "${config}" 2> /dev/null; then 105 | echo ' if [ "x$grub_platform" = xefi ]; then' | sed "s/^/$submenu_indentation/" 106 | echo " set gfxpayload=keep" | sed "s/^/$submenu_indentation/" 107 | echo ' fi' | sed "s/^/$submenu_indentation/" 108 | fi 109 | else 110 | if [ "x$GRUB_GFXPAYLOAD_LINUX" != xtext ]; then 111 | echo " load_video" | sed "s/^/$submenu_indentation/" 112 | fi 113 | echo " set gfxpayload=$GRUB_GFXPAYLOAD_LINUX" | sed "s/^/$submenu_indentation/" 114 | fi 115 | 116 | echo " insmod chain" | sed "s/^/$submenu_indentation/" 117 | 118 | if [ x$dirname = x/ ]; then 119 | if [ -z "${prepare_root_cache}" ]; then 120 | prepare_root_cache="$(prepare_grub_to_access_device ${esp} | grub_add_tab)" 121 | fi 122 | printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/" 123 | else 124 | if [ -z "${prepare_boot_cache}" ]; then 125 | prepare_boot_cache="$(prepare_grub_to_access_device ${esp} | grub_add_tab)" 126 | fi 127 | printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/" 128 | fi 129 | message="$(gettext_printf "Loading UKI %s ..." ${version})" 130 | sed "s/^/$submenu_indentation/" << EOF 131 | echo '$(echo "$message" | grub_quote)' 132 | chainloader ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} 133 | EOF 134 | sed "s/^/$submenu_indentation/" << EOF 135 | } 136 | EOF 137 | } 138 | 139 | machine=`uname -m` 140 | globs="$GRUB_UKI_GLOBS" 141 | [ -z "$globs" ] && globs="/boot/EFI/Linux/*.efi /boot/EFI/EFI/Linux/*.efi /boot/efi/EFI/Linux/*.efi /efi/EFI/Linux/*.efi" 142 | 143 | list= 144 | for i in ${globs} ; do 145 | if grub_file_is_not_garbage "$i" ; then list="$list $i" ; fi 146 | done 147 | 148 | prepare_boot_cache= 149 | prepare_root_cache= 150 | boot_device_id= 151 | title_correction_code= 152 | 153 | # Extra indentation to add to menu entries in a submenu. We're not in a submenu 154 | # yet, so it's empty. In a submenu it will be equal to '\t' (one tab). 155 | submenu_indentation="" 156 | 157 | # Perform a reverse version sort on the entire list. 158 | # Temporarily replace the '.old' suffix by ' 1' and append ' 2' for all 159 | # other files to order the '.old' files after their non-old counterpart 160 | # in reverse-sorted order. 161 | 162 | entry_id_list= 163 | for uki in ${list}; do 164 | entry_id_list="$entry_id_list $(basename -s .efi ${uki%%-*})" 165 | done 166 | 167 | unique_entry_ids=$(echo $entry_id_list | tr ' ' '\n' | sort -u) 168 | 169 | reverse_sorted_list=$(echo $list | tr ' ' '\n' | sed -e 's/\.old$/ 1/; / 1$/! s/$/ 2/' | version_sort -r | sed -e 's/ 1$/.old/; s/ 2$//') 170 | 171 | for entry_id in ${unique_entry_ids}; do 172 | if [ "x$GRUB_TOP_LEVEL" != x ]; then 173 | reverse_sorted_list=$(grub_move_to_front "$GRUB_TOP_LEVEL" ${reverse_sorted_list}) 174 | fi 175 | 176 | is_top_level=true 177 | for linux in ${reverse_sorted_list}; do 178 | base=$(basename -s .efi ${linux}) 179 | if [ "x${base#${entry_id}}" = "x${base}" ]; then 180 | # UKI does not start with our entry ID 181 | continue 182 | fi 183 | gettext_printf "Found unified kernel image: %s\n" "$linux" >&2 184 | basename=`basename $linux` 185 | dirname=`dirname $linux` 186 | rel_dirname=`make_system_path_relative_to_its_root $dirname` 187 | esp=`df -P $linux | tail -1 | cut -d' ' -f 1` 188 | version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` 189 | alt_version=`echo $version | sed -e "s,\.old$,,g"` 190 | linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" 191 | 192 | # The GRUB_DISABLE_SUBMENU option used to be different than others since it was 193 | # mentioned in the documentation that has to be set to 'y' instead of 'true' to 194 | # enable it. This caused a lot of confusion to users that set the option to 'y', 195 | # 'yes' or 'true'. This was fixed but all of these values must be supported now. 196 | if [ "x${GRUB_DISABLE_SUBMENU}" = xyes ] || [ "x${GRUB_DISABLE_SUBMENU}" = xy ]; then 197 | GRUB_DISABLE_SUBMENU="true" 198 | fi 199 | 200 | if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xtrue ]; then 201 | linux_entry "${entry_id}" "${version}" simple \ 202 | "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" 203 | 204 | submenu_indentation="$grub_tab" 205 | 206 | if [ -z "$boot_device_id" ]; then 207 | boot_device_id="$(grub_get_device_id "${GRUB_DEVICE}")" 208 | fi 209 | # TRANSLATORS: %s is replaced with an entry ID 210 | echo "submenu '$(gettext_printf "Advanced options for %s" "${entry_id}" | grub_quote)' \$menuentry_id_option 'gnulinux-advanced-$boot_device_id' {" 211 | is_top_level=false 212 | fi 213 | 214 | linux_entry "${entry_id}" "${version}" advanced \ 215 | "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" 216 | if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then 217 | linux_entry "${entry_id}" "${version}" recovery \ 218 | "${GRUB_CMDLINE_LINUX_RECOVERY} ${GRUB_CMDLINE_LINUX}" 219 | fi 220 | done 221 | 222 | # If at least one kernel was found, then we need to 223 | # add a closing '}' for the submenu command. 224 | if [ x"$is_top_level" != xtrue ]; then 225 | echo '}' 226 | fi 227 | 228 | echo "$title_correction_code" 229 | done 230 | -------------------------------------------------------------------------------- /hooks/30-emerge-kernel-module-rebuild.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2120 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by the 6 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 7 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 8 | # set in the environment. 9 | 10 | ver=${1} 11 | img=${2} 12 | 13 | # Array of external kernel modules to rebuild. 14 | # Use @module-rebuild to rebuild all external kernel modules 15 | MODULES=( 16 | @module-rebuild 17 | ) 18 | 19 | # familiar helpers, we intentionally don't use Gentoo functions.sh 20 | die() { 21 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 22 | exit 1 23 | } 24 | 25 | einfo() { 26 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 27 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 28 | } 29 | 30 | # From multiprocessing.eclass 31 | get_nproc() { 32 | local nproc 33 | 34 | # GNU 35 | if type -P nproc &>/dev/null; then 36 | nproc=$(nproc) 37 | fi 38 | 39 | # BSD 40 | if [[ -z ${nproc} ]] && type -P sysctl &>/dev/null; then 41 | nproc=$(sysctl -n hw.ncpu 2>/dev/null) 42 | fi 43 | 44 | # fallback to python2.6+ 45 | # note: this may fail (raise NotImplementedError) 46 | if [[ -z ${nproc} ]] && type -P python &>/dev/null; then 47 | nproc=$(python -c 'import multiprocessing; print(multiprocessing.cpu_count());' 2>/dev/null) 48 | fi 49 | 50 | if [[ -n ${nproc} ]]; then 51 | echo "${nproc}" 52 | else 53 | echo "${1:-1}" 54 | fi 55 | } 56 | 57 | _get_all_makeopts() { 58 | echo "${MAKEOPTS} ${GNUMAKEFLAGS} ${MAKEFLAGS}" 59 | } 60 | 61 | get_makeopts_jobs() { 62 | makeopts_jobs "$(_get_all_makeopts)" "${1:-1}" 63 | } 64 | 65 | makeopts_jobs() { 66 | [[ $# -eq 0 ]] && set -- "$(_get_all_makeopts)" 67 | # This assumes the first .* will be more greedy than the second .* 68 | # since POSIX doesn't specify a non-greedy match (i.e. ".*?"). 69 | local jobs 70 | jobs=$(echo " $* " | sed -r -n \ 71 | -e 's:.*[[:space:]](-[a-z]*j|--jobs[=[:space:]])[[:space:]]*([0-9]+).*:\2:p' \ 72 | -e "s:.*[[:space:]](-[a-z]*j|--jobs)[[:space:]].*:${2:-$(( $(get_nproc) + 1 ))}:p") 73 | echo "${jobs:-1}" 74 | } 75 | 76 | get_makeopts_loadavg() { 77 | makeopts_loadavg "$(_get_all_makeopts)" "${1:-999}" 78 | } 79 | 80 | makeopts_loadavg() { 81 | [[ $# -eq 0 ]] && set -- "$(_get_all_makeopts)" 82 | # This assumes the first .* will be more greedy than the second .* 83 | # since POSIX doesn't specify a non-greedy match (i.e. ".*?"). 84 | local lavg 85 | lavg=$(echo " $* " | sed -r -n \ 86 | -e 's:.*[[:space:]](-[a-z]*l|--(load-average|max-load)[=[:space:]])[[:space:]]*([0-9]+(\.[0-9]+)?)[[:space:]].*:\3:p' \ 87 | -e "s:.*[[:space:]](-[a-z]*l|--(load-average|max-load))[[:space:]].*:${2:-999}:p") 88 | # Default to ${inf} since the default is to not use a load limit. 89 | echo "${lavg:-${2:-999}}" 90 | } 91 | 92 | main() { 93 | # re-define for subst to work 94 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 95 | 96 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 97 | 98 | local candidates=( 99 | "${ROOT%/}/lib/modules/${ver}/build" 100 | "${ROOT%/}/lib/modules/${ver}/source" 101 | "${ROOT%/}/usr/src/linux-${ver}" 102 | ) 103 | 104 | if [[ "${img:0:1}" == "/" ]]; then 105 | # If the kernel image is an absolute path, try to extract 106 | # the source root from this path 107 | local rel_from_src=${img#*/usr/src/} 108 | candidates+=( 109 | "${ROOT%/}/usr/src/${rel_from_src%%/*}" 110 | ) 111 | else 112 | # If the kernel image is a relative path try the pwd as well 113 | candidates+=( 114 | "$(pwd)" 115 | ) 116 | fi 117 | 118 | for dir in "${candidates[@]}"; do 119 | if [[ -d ${dir} ]]; then 120 | KERNEL_DIR="${dir}" 121 | break 122 | fi 123 | done 124 | 125 | if [[ -d ${KERNEL_DIR} ]]; then 126 | einfo "Using kernel sources directory: ${KERNEL_DIR}" 127 | else 128 | die "Kernel sources directory not found" 129 | fi 130 | 131 | local emerge_opts=( 132 | --oneshot 133 | --jobs="$(get_makeopts_jobs)" 134 | --load-average="$(get_makeopts_loadavg)" 135 | --ignore-default-opts 136 | ) 137 | 138 | # Since we are sort of running emerge from emerge/make we start with 139 | # a dirty environment which creates a mess. Start clean instead and 140 | # disable ebuild-locks. 141 | # Binpkgs don't make sense here, they don't contain information on which 142 | # kernel version they were built for. 143 | # USE=dist-kernel doesn't make sense here, we would end up rebuilding twice. 144 | # Instruct linux-mod(-r1).eclass (via linux-info.eclass) to use the just 145 | # installed kernel instead of the eselected one. 146 | einfo "Rebuilding out-of-tree kernel modules..." 147 | env -i \ 148 | PATH="${PATH}" \ 149 | FEATURES="-getbinpkg -buildpkg -ebuild-locks parallel-install" \ 150 | USE="-dist-kernel" \ 151 | KERNEL_DIR="${KERNEL_DIR}" \ 152 | emerge "${emerge_opts[@]}" "${MODULES[@]}" || die 153 | } 154 | 155 | main 156 | -------------------------------------------------------------------------------- /hooks/50-dracut.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by the 5 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 6 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 7 | # set in the environment. 8 | 9 | ver=${1} 10 | img=${2} 11 | basedir=$(dirname "${img}") 12 | initrd=${INSTALLKERNEL_STAGING_AREA:-${basedir}}/initrd 13 | uki=${INSTALLKERNEL_STAGING_AREA:-${basedir}}/uki.efi 14 | tmp=${INSTALLKERNEL_STAGING_AREA:-${basedir}}/dracut-tmp 15 | 16 | # familiar helpers, we intentionally don't use Gentoo functions.sh 17 | die() { 18 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 19 | exit 1 20 | } 21 | 22 | einfo() { 23 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 24 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 25 | } 26 | 27 | ewarn() { 28 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 29 | } 30 | 31 | main() { 32 | # re-define for subst to work 33 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 34 | 35 | if [[ -n "${INSTALLKERNEL_INITRD_GENERATOR}" && 36 | ${INSTALLKERNEL_INITRD_GENERATOR} != dracut ]]; then 37 | # We are not selected as the initrd generator 38 | einfo "initrd_generator=${INSTALLKERNEL_INITRD_GENERATOR}, skipping dracut" 39 | exit 0 40 | fi 41 | 42 | # do nothing if somehow dracut is not installed 43 | [[ -x $(command -v dracut) ]] || { ewarn "dracut is not installed, not generating an initramfs" && exit 0; } 44 | 45 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 46 | 47 | initramfs_gen_args=( 48 | --add-confdir hostonly 49 | # if uefi=yes is used, dracut needs to locate the kernel image 50 | --kernel-image "${img}" 51 | ) 52 | 53 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] && initramfs_gen_args+=( --verbose ) 54 | 55 | if [[ ${INSTALLKERNEL_UKI_GENERATOR} == dracut ]]; then 56 | einfo "Using dracut as the initramfs and UKI generator..." 57 | initramfs_gen_args+=( --uefi ) 58 | out="${uki}" 59 | if [[ -f $(dirname "${img}")/uki.efi ]]; then 60 | einfo "There is an UKI image at the same place as the kernel, skipping generating a new one" 61 | cp --reflink=auto "$(dirname "${img}")/uki.efi" "${uki}" || die 62 | chown root:root "${uki}" || die 63 | chmod 0600 "${uki}" || die 64 | exit 0 65 | fi 66 | elif [[ ${INSTALLKERNEL_INITRD_GENERATOR} == dracut ]]; then 67 | einfo "Using dracut as the initramfs generator..." 68 | initramfs_gen_args+=( --no-uefi ) 69 | out="${initrd}" 70 | if [[ -f $(dirname "${img}")/initrd ]]; then 71 | einfo "There is an initramfs image at the same place as the kernel, skipping generating a new one" 72 | cp --reflink=auto "$(dirname "${img}")/initrd" "${initrd}" || die 73 | chown root:root "${initrd}" || die 74 | chmod 0600 "${initrd}" || die 75 | exit 0 76 | fi 77 | else 78 | einfo "No install.conf preference set, falling back to dracut.conf..." 79 | out="${tmp}" 80 | fi 81 | 82 | initramfs_gen_args+=( 83 | # positional arguments 84 | "${out}" "${ver}" 85 | ) 86 | 87 | dracut "${initramfs_gen_args[@]}" || die "Failed to generate initramfs" 88 | 89 | # Fallback path for if we don't know if we generated an initramfs or 90 | # UKI. If dracut is used in uefi=yes mode, initrd will actually 91 | # be a combined kernel+initramfs UEFI executable. We can easily 92 | # recognize it by PE magic (vs cpio for a regular initramfs) 93 | if [[ -s ${tmp} ]]; then 94 | read -rn 2 magic <"${tmp}" || die "Cannot read ${tmp}" 95 | if [[ ${magic} == MZ ]]; then 96 | einfo "Combined UEFI kernel+initramfs executable found" 97 | mv "${tmp}" "${uki}" || die "Failed to rename UKI" 98 | else 99 | einfo "Plain initramfs image found" 100 | mv "${tmp}" "${initrd}" || die "Failed to rename initramfs" 101 | fi 102 | fi 103 | } 104 | 105 | main 106 | -------------------------------------------------------------------------------- /hooks/60-ukify.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by the 5 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 6 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 7 | # set in the environment. 8 | 9 | ver=${1} 10 | img=${2} 11 | 12 | # familiar helpers, we intentionally don't use Gentoo functions.sh 13 | die() { 14 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 15 | exit 1 16 | } 17 | 18 | einfo() { 19 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 20 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 21 | } 22 | 23 | ewarn() { 24 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 25 | } 26 | 27 | find_config_file() { 28 | file=${1} 29 | if [[ -f "/etc/kernel/${file}" ]]; then 30 | echo "/etc/kernel/${file}" 31 | elif [[ -f "/usr/lib/kernel/${file}" ]]; then 32 | echo "/usr/lib/kernel/${file}" 33 | fi 34 | } 35 | 36 | main() { 37 | # re-define for subst to work 38 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 39 | 40 | if [[ -n "${INSTALLKERNEL_UKI_GENERATOR}" && 41 | ${INSTALLKERNEL_UKI_GENERATOR} != ukify ]]; then 42 | # We are not selected as the uki generator 43 | einfo "uki_generator=${INSTALLKERNEL_UKI_GENERATOR}, skipping ukify" 44 | exit 0 45 | fi 46 | 47 | if [[ -n "${INSTALLKERNEL_LAYOUT}" && ${INSTALLKERNEL_LAYOUT} != uki ]]; then 48 | einfo "layout=${INSTALLKERNEL_LAYOUT}, skipping ukify" 49 | exit 0 50 | fi 51 | 52 | # do nothing if somehow ukify is not installed 53 | if [[ -x /usr/lib/systemd/ukify ]]; then 54 | ukify=/usr/lib/systemd/ukify 55 | elif [[ -x /lib/systemd/ukify ]]; then 56 | ukify=/lib/systemd/ukify 57 | else 58 | ewarn "ukify is not installed, not generating an UKI" && exit 0 59 | fi 60 | 61 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 62 | 63 | ukify_gen_args=( 64 | build 65 | --linux="${img}" 66 | --uname="${ver}" 67 | --output="${INSTALLKERNEL_STAGING_AREA}/uki.efi" 68 | ) 69 | 70 | for cpu in intel amd; do 71 | [[ -f "/boot/${cpu}-uc.img" ]] && ukify_gen_args+=(--initrd="/boot/${cpu}-uc.img") 72 | done 73 | 74 | initrd="${INSTALLKERNEL_STAGING_AREA}/initrd" 75 | [[ -f ${initrd} ]] && ukify_gen_args+=(--initrd="${initrd}") 76 | 77 | # Use the same files as systemd's 60-ukify.install 78 | cmdline=$(find_config_file cmdline) 79 | [[ "${cmdline}" ]] && ukify_gen_args+=(--cmdline=@"${cmdline}") 80 | 81 | ukiconf=$(find_config_file uki.conf) 82 | [[ "${ukiconf}" ]] && ukify_gen_args+=(--config="${ukiconf}") 83 | 84 | devicetree_config=$(find_config_file devicetree) 85 | if [[ "${devicetree_config}" ]]; then 86 | devicetree_path=$(cat "${devicetree_config}") 87 | if [[ -f "/usr/lib/firmware/${ver}/device-tree/${devicetree_path}" ]]; then 88 | ukify_gen_args+=(--devicetree="/usr/lib/firmware/${ver}/device-tree/${devicetree_path}") 89 | elif [[ -f "/usr/lib/linux-image-${ver}/${devicetree_path}" ]]; then 90 | ukify_gen_args+=(--devicetree="/usr/lib/linux-image-${ver}/${devicetree_path}") 91 | elif [[ -f "/usr/lib/modules/${ver}/dtb/${devicetree_path}" ]]; then 92 | ukify_gen_args+=(--devicetree="/usr/lib/modules/${ver}/dtb/${devicetree_path}") 93 | fi 94 | fi 95 | 96 | if [[ ${SECUREBOOT_SIGN_KEY} == pkcs11:* ]]; then 97 | ukify_gen_args+=( 98 | --secureboot-private-key="${SECUREBOOT_SIGN_KEY}" 99 | --signtool=sbsign 100 | --signing-engine=pkcs11 101 | ) 102 | elif [[ -r ${SECUREBOOT_SIGN_KEY} ]]; then 103 | ukify_gen_args+=( 104 | --secureboot-private-key="${SECUREBOOT_SIGN_KEY}" 105 | ) 106 | fi 107 | 108 | if [[ -r ${SECUREBOOT_SIGN_CERT} ]]; then 109 | ukify_gen_args+=( 110 | --secureboot-certificate="${SECUREBOOT_SIGN_CERT}" 111 | ) 112 | fi 113 | 114 | einfo "Calling ukify with arguments: ${ukify_gen_args[*]}" 115 | ${ukify} "${ukify_gen_args[@]}" || die "Failed to generate UKI" 116 | } 117 | 118 | main 119 | -------------------------------------------------------------------------------- /hooks/91-grub-mkconfig.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by the 5 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 6 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 7 | # set in the environment. 8 | 9 | : "${GRUB_CFG:=/boot/grub/grub.cfg}" 10 | 11 | # familiar helpers, we intentionally don't use Gentoo functions.sh 12 | die() { 13 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 14 | exit 1 15 | } 16 | 17 | einfo() { 18 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 19 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 20 | } 21 | 22 | ewarn() { 23 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 24 | } 25 | 26 | eerror() { 27 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 28 | } 29 | 30 | main() { 31 | # re-define for subst to work 32 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 33 | 34 | # do nothing if somehow GRUB is not installed 35 | [[ -x $(command -v grub-mkconfig) ]] || { ewarn "grub-mkconfig command not available" && exit 0; } 36 | 37 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 38 | 39 | if [[ -f ${GRUB_CFG} ]]; then 40 | einfo "Backing up existing grub config as ${GRUB_CFG}~..." 41 | cp --dereference --preserve=all "${GRUB_CFG}"{,~} || die "Failed to save existing config" 42 | fi 43 | 44 | if [[ -f /etc/os-release ]]; then 45 | # shellcheck source=/dev/null 46 | . /etc/os-release 47 | elif [[ -f /usr/lib/os-release ]]; then 48 | # shellcheck source=/dev/null 49 | . /usr/lib/os-release 50 | fi 51 | 52 | # Set sane default if no or broken os-release 53 | : "${NAME:=Linux}" 54 | 55 | # The default GRUB_LINUX_KERNEL_GLOBS from /etc/grub/10_linux expanded 56 | # with efistub dir 57 | : "${GRUB_LINUX_KERNEL_GLOBS:=" 58 | /boot/vmlinuz-* /boot/vmlinux-* /boot/kernel-* /vmlinuz-* /vmlinux-* /kernel-* 59 | /boot/EFI/EFI/${NAME}/vmlinuz-*.efi /boot/EFI/EFI/${NAME}/vmlinux-*.efi 60 | /boot/EFI/EFI/${NAME}/kernel-*.efi /boot/efi/EFI/${NAME}/vmlinuz-*.efi 61 | /boot/efi/EFI/${NAME}/vmlinux-*.efi /boot/efi/EFI/${NAME}/kernel-*.efi 62 | /boot/EFI/${NAME}/vmlinuz-*.efi /boot/EFI/${NAME}/vmlinux-*.efi 63 | /boot/EFI/${NAME}/kernel-*.efi /efi/EFI/${NAME}/vmlinuz-*.efi 64 | /efi/EFI/${NAME}/vmlinux-*.efi /efi/EFI/${NAME}/kernel-*.efi 65 | "}" 66 | export GRUB_LINUX_KERNEL_GLOBS 67 | 68 | einfo "Generating new GRUB config as ${GRUB_CFG}..." 69 | local dname="${GRUB_CFG%/*}" 70 | mkdir -vp "${dname}" || die "Failed to mkdir ${dname}" 71 | # Exit non-fatally to ensure emerge does not fail completely in containers 72 | grub-mkconfig -o "${GRUB_CFG}" || eerror "grub-mkconfig failed" 73 | } 74 | 75 | main 76 | -------------------------------------------------------------------------------- /hooks/95-efistub-uefi-mkconfig.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2020-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by the 5 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 6 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 7 | # set in the environment. 8 | 9 | # familiar helpers, we intentionally don't use Gentoo functions.sh 10 | die() { 11 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 12 | exit 1 13 | } 14 | 15 | einfo() { 16 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 17 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 18 | } 19 | 20 | ewarn() { 21 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 22 | } 23 | 24 | main() { 25 | # re-define for subst to work 26 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 27 | 28 | # do nothing if somehow uefi-mkconfig is not installed 29 | [[ -x $(command -v uefi-mkconfig) ]] || { ewarn "uefi-mkconfig command not available" && exit 0; } 30 | 31 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 32 | 33 | einfo "Updating UEFI configuration..." 34 | uefi-mkconfig || die "uefi-mkconfig failed" 35 | } 36 | 37 | main 38 | -------------------------------------------------------------------------------- /hooks/95-refind-copy-icon.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by the 6 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 7 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 8 | # set in the environment. 9 | 10 | ver=${1} 11 | img=${2} 12 | 13 | if [[ $(getconf LONG_BIT) == 64 ]]; then 14 | : "${REFIND_ICON:=/usr/lib64/refind/refind/icons/os_${ID}.png}" 15 | else 16 | : "${REFIND_ICON:=/usr/lib/refind/refind/icons/os_${ID}.png}" 17 | fi 18 | 19 | # familiar helpers, we intentionally don't use Gentoo functions.sh 20 | die() { 21 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 22 | exit 1 23 | } 24 | 25 | einfo() { 26 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 27 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 28 | } 29 | 30 | main() { 31 | # re-define for subst to work 32 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 33 | 34 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 35 | 36 | if [[ ! -f ${REFIND_ICON} ]]; then 37 | die "REFIND_ICON=${REFIND_ICON} not found" 38 | fi 39 | 40 | einfo "Copying rEFInd icon file..." 41 | local icon="${img%.efi}.png" 42 | local icon_old=${icon%.png}.old.png 43 | if [[ ${INSTALLKERNEL_LAYOUT} == efistub || 44 | ${INSTALLKERNEL_LAYOUT} == uki ]]; then 45 | icon_old=${icon%.png}-old.png 46 | fi 47 | # If already installed, then move icon for the .old kernel 48 | if [[ -f ${icon} ]]; then 49 | mv "${icon}" "${icon_old}" || die 50 | fi 51 | cp --dereference --preserve=all "${REFIND_ICON}" "${icon}" || die "Failed to copy icon file" 52 | 53 | # If there is a version-less image, install an icon for it 54 | local icon_nover=${icon//-${ver}/} 55 | local icon_nover_old=${icon_nover%.png}.old.png 56 | if [[ ${INSTALLKERNEL_LAYOUT} == efistub || 57 | ${INSTALLKERNEL_LAYOUT} == uki ]]; then 58 | icon_nover_old=${icon_nover%.png}-old.png 59 | fi 60 | 61 | if [[ -L ${icon_nover} ]]; then 62 | if [[ "$(readlink -f "${icon_nover}")" == "${icon}" ]]; then 63 | ln -sf "$(basename "${icon_old}")" "${icon_nover_old}" || die 64 | else 65 | mv "${icon_nover}" "${icon_nover_old}" || die 66 | fi 67 | ln -sf "$(basename "${icon}")" "${icon_nover}" || die 68 | elif [[ -f ${icon_nover} ]]; then 69 | mv "${icon_nover}" "${icon_nover_old}" || die 70 | cp --dereference --preserve=all "${icon}" "${icon_nover}" || die 71 | elif [[ -L ${img//-${ver}/} ]]; then 72 | ln -sf "$(basename "${icon}")" "${icon_nover}" || die 73 | elif [[ -f ${img//-${ver}/} ]]; then 74 | cp --dereference --preserve=all "${icon}" "${icon_nover}" || die 75 | fi 76 | } 77 | 78 | main 79 | -------------------------------------------------------------------------------- /hooks/99-check-diskspace.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by the 6 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 7 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 8 | # set in the environment. 9 | 10 | ver=${1} 11 | img=${2} 12 | basedir=$(dirname "${img}") 13 | initrd=${INSTALLKERNEL_STAGING_AREA:-${basedir}}/initrd 14 | uki=${INSTALLKERNEL_STAGING_AREA:-${basedir}}/uki.efi 15 | 16 | # familiar helpers, we intentionally don't use Gentoo functions.sh 17 | die() { 18 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 19 | exit 1 20 | } 21 | 22 | einfo() { 23 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 24 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 25 | } 26 | 27 | ewarn() { 28 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 29 | } 30 | 31 | eerror() { 32 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 33 | } 34 | 35 | main() { 36 | # re-define for subst to work 37 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 38 | 39 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 40 | 41 | local install_dir=/boot 42 | if [[ ${INSTALLKERNEL_LAYOUT} == "uki" ]]; then 43 | for candidate in /boot/EFI /boot/efi /boot /efi; do 44 | if [[ -d ${candidate}/EFI/Linux ]]; then 45 | install_dir=${candidate}/EFI/Linux 46 | else 47 | continue 48 | fi 49 | done 50 | elif [[ ${INSTALLKERNEL_LAYOUT} == "efistub" ]]; then 51 | for candidate in /boot/EFI /boot/efi /boot /efi; do 52 | if [[ -d ${candidate}/EFI/${NAME} ]]; then 53 | install_dir=${candidate}/EFI/${NAME} 54 | else 55 | continue 56 | fi 57 | done 58 | fi 59 | 60 | einfo "Checking available disk space on ${install_dir}..." 61 | local space_kbi 62 | space_kbi=$(df -Pk "${install_dir}" 2>/dev/null | awk 'FNR == 2 {print $4}') 63 | 64 | if [[ ${?} == 0 && -n ${space_kbi} ]]; then 65 | # Add the typical size of a refind icon(8), bls entry(4) file, typical 66 | # config (272) and System.map(9852) 67 | local required=10200 68 | if [[ ${INSTALLKERNEL_LAYOUT} == "uki" ]]; then 69 | if [[ -f ${uki} ]]; then 70 | required=$((required + $(du -kx "${uki}" | awk 'FNR == 1 {print $1}'))) 71 | fi 72 | else 73 | required=$((required + $(du -kx "${img}" | awk 'FNR == 1 {print $1}'))) 74 | if [[ -f ${initrd} ]]; then 75 | required=$((required + $(du -kx "${initrd}" | awk 'FNR == 1 {print $1}'))) 76 | fi 77 | fi 78 | if [[ ${space_kbi} -lt ${required} ]]; then 79 | eerror "Not enough disk space. Need at least ${required} KiB, found ${space_kbi} KiB." 80 | die "Please use app-admin/eclean-kernel to clean up old kernels." 81 | else 82 | einfo "Disk space okay. Need at least ${required} KiB, found ${space_kbi} KiB." 83 | fi 84 | else 85 | ewarn "Failed to determine disk space." 86 | fi 87 | } 88 | 89 | main 90 | -------------------------------------------------------------------------------- /hooks/99-write-log.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034,SC2140 3 | 4 | # Copyright 2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by the 6 | # traditional installkernel, NOT by systemd's kernel-install. I.e. this plugin 7 | # is run when the systemd USE flag is disabled or SYSTEMD_KERNEL_INSTALL=0 is 8 | # set in the environment. 9 | 10 | ver=${1} 11 | img=${2} 12 | 13 | # familiar helpers, we intentionally don't use Gentoo functions.sh 14 | die() { 15 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 16 | exit 1 17 | } 18 | 19 | einfo() { 20 | [[ ${INSTALLKERNEL_VERBOSE} == 1 ]] || return 0 21 | echo -e " ${NOCOLOR-\e[1;32m*\e[0m }${*}" 22 | } 23 | 24 | ewarn() { 25 | echo -e " ${NOCOLOR-\e[1;33m*\e[0m }${*}" 26 | } 27 | 28 | eerror() { 29 | echo -e " ${NOCOLOR-\e[1;31m*\e[0m }${*}" >&2 30 | } 31 | 32 | main() { 33 | # re-define for subst to work 34 | [[ -n ${NOCOLOR+yes} ]] && NOCOLOR= 35 | 36 | [[ ${EUID} -eq 0 ]] || die "Please run this script as root" 37 | 38 | local install_dir=/boot 39 | local kernel= 40 | local initrd= 41 | if [[ ${INSTALLKERNEL_LAYOUT} == "uki" ]]; then 42 | for candidate in /boot/EFI /boot/efi /boot /efi; do 43 | if [[ -d ${candidate}/EFI/Linux ]]; then 44 | install_dir=${candidate} 45 | else 46 | continue 47 | fi 48 | done 49 | kernel=${install_dir}/EFI/Linux/${ID}-${ver}.efi 50 | initrd= 51 | elif [[ ${INSTALLKERNEL_LAYOUT} == "efistub" ]]; then 52 | for candidate in /boot/EFI /boot/efi /boot /efi; do 53 | if [[ -d ${candidate}/EFI/${NAME} ]]; then 54 | install_dir=${candidate} 55 | else 56 | continue 57 | fi 58 | done 59 | kernel=${install_dir}/EFI/${NAME}/vmlinuz-${ver}.efi 60 | initrd=${install_dir}/EFI/${NAME}/initramfs-${ver}.img 61 | elif [[ ${INSTALLKERNEL_LAYOUT} == "compat" || ${INSTALLKERNEL_LAYOUT} == "grub" ]]; then 62 | kernel=${install_dir}/vmlinuz-${ver} 63 | initrd=${install_dir}/initramfs-${ver}.img 64 | else 65 | ewarn "WARNING: unknown layout, log will be incomplete" 66 | KERNEL=unknown 67 | INITRD= 68 | fi 69 | [[ ! -f ${initrd} ]] && initrd=unknown 70 | [[ ! -f ${kernel} ]] && kernel=unknown 71 | 72 | INSTALLKERNEL_PLUGINS="${INSTALLKERNEL_PREINST_PLUGINS:+${INSTALLKERNEL_PREINST_PLUGINS} }${INSTALLKERNEL_POSTINST_PLUGINS}" 73 | 74 | if [[ -z ${INSTALLKERNEL_CONF_ROOT} ]]; then 75 | if [[ -f /etc/kernel/install.conf ]]; then 76 | INSTALLKERNEL_CONF_ROOT=/etc/kernel 77 | elif [[ -f /usr/lib/kernel/install.conf ]]; then 78 | INSTALLKERNEL_CONF_ROOT=/usr/lib/kernel 79 | fi 80 | fi 81 | 82 | local state=/var/lib/misc/installkernel 83 | local log=/var/log/installkernel.log 84 | 85 | einfo "Appending installed kernel to ${log}..." 86 | 87 | 88 | #shellcheck disable=SC2155 89 | local logline=\ 90 | "$(LC_ALL=C date)\t"\ 91 | "gentoo\t"\ 92 | "${ver:-notset}\t"\ 93 | "${INSTALLKERNEL_CONF_ROOT:-notset}\t"\ 94 | "${INSTALLKERNEL_LAYOUT:-notset}\t"\ 95 | "${INSTALLKERNEL_INITRD_GENERATOR:-notset}\t"\ 96 | "${INSTALLKERNEL_UKI_GENERATOR:-notset}\t"\ 97 | "${install_dir:-notset}\t"\ 98 | "${kernel#"${install_dir}/"}\t"\ 99 | "${initrd#"${install_dir}/"}\t"\ 100 | "${INSTALLKERNEL_PLUGINS:-notset}" 101 | 102 | echo -e "${logline}" > "${state}" || exit 1 103 | echo -e "${logline}" >> "${log}" || exit 1 104 | } 105 | 106 | main 107 | -------------------------------------------------------------------------------- /hooks/systemd/00-00machineid-directory.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Copyright 2023-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by 5 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 6 | # plugin is run when the systemd USE flag is enabled or 7 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 8 | 9 | COMMAND="${1}" 10 | ENTRY_DIR_ABS="${3}" 11 | 12 | # this is exported by kernel-install 13 | if [ -z "${KERNEL_INSTALL_MACHINE_ID}" ]; then 14 | exit 0 15 | fi 16 | 17 | if [ "${KERNEL_INSTALL_LAYOUT}" != "bls" ]; then 18 | exit 0 19 | fi 20 | 21 | if [ "${COMMAND}" != "add" ]; then 22 | exit 0 23 | fi 24 | 25 | # If the machine-id dir does not exist (e.g. $ESP/) 26 | # create it. It receives values directly from kernel-install. 27 | # This is the only function of this plugin. 28 | MACHINE_ID_DIR="${ENTRY_DIR_ABS%/*}" 29 | if ! [ -d "${MACHINE_ID_DIR}" ]; then 30 | if [ "${KERNEL_INSTALL_VERBOSE}" = "1" ]; then 31 | echo "+mkdir -v -p ${MACHINE_ID_DIR}" 32 | mkdir -v -p "${MACHINE_ID_DIR}" 33 | else 34 | mkdir -p "${MACHINE_ID_DIR}" 35 | fi 36 | fi 37 | -------------------------------------------------------------------------------- /hooks/systemd/10-copy-prebuilt.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # Copyright 2023-2024 Gentoo Authors 4 | # This script is installed by sys-kernel/installkernel, it is executed by 5 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 6 | # plugin is run when the systemd USE flag is enabled or 7 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 8 | 9 | COMMAND="${1}" 10 | KERNEL_IMAGE="${4}" 11 | 12 | if [ "${COMMAND}" != "add" ]; then 13 | exit 0 14 | fi 15 | 16 | IMAGE_DIR=$(dirname "${KERNEL_IMAGE}") 17 | INITRD=${IMAGE_DIR}/initrd 18 | UKI=${IMAGE_DIR}/uki.efi 19 | 20 | if [ -f "${INITRD}" ]; then 21 | [ "${KERNEL_INSTALL_VERBOSE}" = "1" ] && echo "Copying prebuilt initramfs to staging area" 22 | cp --dereference --preserve=all "${INITRD}" "${KERNEL_INSTALL_STAGING_AREA}/initrd" || exit 1 23 | fi 24 | 25 | if [ -f "${UKI}" ]; then 26 | [ "${KERNEL_INSTALL_VERBOSE}" = "1" ] && echo "Copying prebuilt UKI to staging area" 27 | cp --dereference --preserve=all "${UKI}" "${KERNEL_INSTALL_STAGING_AREA}/uki.efi" || exit 1 28 | fi 29 | 30 | if [ -f "/boot/intel-uc.img" ]; then 31 | [ "${KERNEL_INSTALL_VERBOSE}" = "1" ] && echo "Copying prebuilt Intel early microcode image to staging area" 32 | cp --dereference --preserve=all "/boot/intel-uc.img" "${KERNEL_INSTALL_STAGING_AREA}/microcode-intel" || exit 1 33 | fi 34 | 35 | if [ -f "/boot/amd-uc.img" ]; then 36 | [ "${KERNEL_INSTALL_VERBOSE}" = "1" ] && echo "Copying prebuilt AMD early microcode image to staging area" 37 | cp --dereference --preserve=all "/boot/amd-uc.img" "${KERNEL_INSTALL_STAGING_AREA}/microcode-amd" || exit 1 38 | fi 39 | -------------------------------------------------------------------------------- /hooks/systemd/30-emerge-kernel-module-rebuild.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2120,SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | ENTRY_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [[ "${COMMAND}" != "add" ]]; then 16 | exit 0 17 | fi 18 | 19 | # Array of external kernel modules to rebuild. 20 | # Use @module-rebuild to rebuild all external kernel modules 21 | MODULES=( 22 | @module-rebuild 23 | ) 24 | 25 | candidates=( 26 | "${ROOT%/}/lib/modules/${KERNEL_VERSION}/build" 27 | "${ROOT%/}/lib/modules/${KERNEL_VERSION}/source" 28 | "${ROOT%/}/usr/src/linux-${KERNEL_VERSION}" 29 | ) 30 | 31 | if [[ "${KERNEL_IMAGE:0:1}" == "/" ]]; then 32 | # If the kernel image is an absolute path, try to extract 33 | # the source root from this path 34 | rel_from_src=${KERNEL_IMAGE#*/usr/src/} 35 | candidates+=( 36 | "${ROOT%/}/usr/src/${rel_from_src%%/*}" 37 | ) 38 | else 39 | # If the kernel image is a relative path try the pwd as well 40 | candidates+=( 41 | "$(pwd)" 42 | ) 43 | fi 44 | 45 | for dir in "${candidates[@]}"; do 46 | if [[ -d ${dir} ]]; then 47 | KERNEL_DIR="${dir}" 48 | break 49 | fi 50 | done 51 | 52 | if [[ -d ${KERNEL_DIR} ]]; then 53 | if [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]]; then 54 | echo "Using kernel sources directory: ${KERNEL_DIR}" 55 | fi 56 | else 57 | echo "Kernel sources directory not found" 58 | exit 1 59 | fi 60 | 61 | 62 | # From multiprocessing.eclass 63 | get_nproc() { 64 | local nproc 65 | 66 | # GNU 67 | if type -P nproc &>/dev/null; then 68 | nproc=$(nproc) 69 | fi 70 | 71 | # BSD 72 | if [[ -z ${nproc} ]] && type -P sysctl &>/dev/null; then 73 | nproc=$(sysctl -n hw.ncpu 2>/dev/null) 74 | fi 75 | 76 | # fallback to python2.6+ 77 | # note: this may fail (raise NotImplementedError) 78 | if [[ -z ${nproc} ]] && type -P python &>/dev/null; then 79 | nproc=$(python -c 'import multiprocessing; print(multiprocessing.cpu_count());' 2>/dev/null) 80 | fi 81 | 82 | if [[ -n ${nproc} ]]; then 83 | echo "${nproc}" 84 | else 85 | echo "${1:-1}" 86 | fi 87 | } 88 | 89 | _get_all_makeopts() { 90 | echo "${MAKEOPTS} ${GNUMAKEFLAGS} ${MAKEFLAGS}" 91 | } 92 | 93 | get_makeopts_jobs() { 94 | makeopts_jobs "$(_get_all_makeopts)" "${1:-1}" 95 | } 96 | 97 | makeopts_jobs() { 98 | [[ $# -eq 0 ]] && set -- "$(_get_all_makeopts)" 99 | # This assumes the first .* will be more greedy than the second .* 100 | # since POSIX doesn't specify a non-greedy match (i.e. ".*?"). 101 | local jobs 102 | jobs=$(echo " $* " | sed -r -n \ 103 | -e 's:.*[[:space:]](-[a-z]*j|--jobs[=[:space:]])[[:space:]]*([0-9]+).*:\2:p' \ 104 | -e "s:.*[[:space:]](-[a-z]*j|--jobs)[[:space:]].*:${2:-$(( $(get_nproc) + 1 ))}:p") 105 | echo "${jobs:-1}" 106 | } 107 | 108 | get_makeopts_loadavg() { 109 | makeopts_loadavg "$(_get_all_makeopts)" "${1:-999}" 110 | } 111 | 112 | makeopts_loadavg() { 113 | [[ $# -eq 0 ]] && set -- "$(_get_all_makeopts)" 114 | # This assumes the first .* will be more greedy than the second .* 115 | # since POSIX doesn't specify a non-greedy match (i.e. ".*?"). 116 | local lavg 117 | lavg=$(echo " $* " | sed -r -n \ 118 | -e 's:.*[[:space:]](-[a-z]*l|--(load-average|max-load)[=[:space:]])[[:space:]]*([0-9]+(\.[0-9]+)?)[[:space:]].*:\3:p' \ 119 | -e "s:.*[[:space:]](-[a-z]*l|--(load-average|max-load))[[:space:]].*:${2:-999}:p") 120 | # Default to ${inf} since the default is to not use a load limit. 121 | echo "${lavg:-${2:-999}}" 122 | } 123 | 124 | emerge_opts=( 125 | --oneshot 126 | --jobs="$(get_makeopts_jobs)" 127 | --load-average="$(get_makeopts_loadavg)" 128 | --ignore-default-opts 129 | ) 130 | 131 | if [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]]; then 132 | emerge_opts+=( 133 | --verbose 134 | ) 135 | else 136 | emerge_opts+=( 137 | --quiet=y 138 | --quiet-fail=y 139 | --quiet-build=y 140 | ) 141 | fi 142 | 143 | # Since we are sort of running emerge from emerge/make we start with 144 | # a dirty environment which creates a mess. Start clean instead and 145 | # disable ebuild-locks. 146 | # Binpkgs don't make sense here, they don't contain information on which 147 | # kernel version they were built for. 148 | # USE=dist-kernel doesn't make sense here, we would end up rebuilding twice. 149 | # Instruct linux-mod(-r1).eclass (via linux-info.eclass) to use the just 150 | # installed kernel instead of the eselected one. 151 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Rebuilding out-of-tree kernel modules..." 152 | env -i \ 153 | PATH="${PATH}" \ 154 | FEATURES="-getbinpkg -buildpkg -ebuild-locks parallel-install" \ 155 | USE="-dist-kernel" \ 156 | KERNEL_DIR="${KERNEL_DIR}" \ 157 | emerge "${emerge_opts[@]}" "${MODULES[@]}" || exit 1 158 | -------------------------------------------------------------------------------- /hooks/systemd/85-check-diskspace.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | BOOT_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [[ ${COMMAND} != add ]]; then 16 | exit 0 17 | fi 18 | 19 | if [[ ${KERNEL_INSTALL_LAYOUT} == "grub" || ${KERNEL_INSTALL_LAYOUT} == "compat" ]]; then 20 | KERNEL_INSTALL_BOOT_ROOT="/boot" 21 | fi 22 | 23 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Checking available disk space on ${KERNEL_INSTALL_BOOT_ROOT}..." 24 | 25 | space_kbi=$(df -Pk "${KERNEL_INSTALL_BOOT_ROOT}" 2>/dev/null | awk 'FNR == 2 {print $4}') 26 | 27 | if [[ ${?} == 0 && -n ${space_kbi} ]]; then 28 | # Add the typical size of a refind icon(8) and bls entry(4) file to be safe 29 | required=15 30 | if [[ ${KERNEL_INSTALL_LAYOUT} == "uki" ]]; then 31 | UKI=${KERNEL_INSTALL_STAGING_AREA}/uki.efi 32 | if [[ -f ${UKI} ]]; then 33 | required=$((required + $(du -kx "${UKI}" | awk 'FNR == 1 {print $1}'))) 34 | fi 35 | else 36 | required=$((required + $(du -kx "${KERNEL_IMAGE}" | awk 'FNR == 1 {print $1}'))) 37 | INITRD=${KERNEL_INSTALL_STAGING_AREA}/initrd 38 | if [[ -f ${INITRD} ]]; then 39 | required=$((required + $(du -kx "${INITRD}" | awk 'FNR == 1 {print $1}'))) 40 | fi 41 | for CPU in intel amd; do 42 | UCODE=${KERNEL_INSTALL_STAGING_AREA}/microcode-${CPU} 43 | if [[ -f ${UCODE} ]]; then 44 | required=$((required + $(du -kx "${UCODE}" | awk 'FNR == 1 {print $1}'))) 45 | fi 46 | done 47 | fi 48 | if [[ ${space_kbi} -lt ${required} ]]; then 49 | echo "ERROR: Not enough disk space. Need at least ${required} KiB, found ${space_kbi} KiB." 50 | echo "Please use app-admin/eclean-kernel to clean up old kernels." 51 | exit 1 52 | else 53 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ 54 | "Disk space okay. Need at least ${required} KiB, found ${space_kbi} KiB." 55 | exit 0 56 | fi 57 | else 58 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "WARNING: Failed to determine disk space." 59 | exit 0 60 | fi 61 | -------------------------------------------------------------------------------- /hooks/systemd/90-compat.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | BOOT_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [[ ${KERNEL_INSTALL_LAYOUT} == "grub" || ${KERNEL_INSTALL_LAYOUT} == "compat" ]]; then 16 | # kernel-install insists on using the EFI partition as BOOT_ROOT. And ignores 17 | # the variable if it does not point to the root of a FAT partition. 18 | # This is what we want for systemd-boot, but it is definitely not what we want 19 | # for GRUB. grub-install (by default) installs a grub efi executable that 20 | # always loads /boot/grub/grub.cfg, this will break if the BOOT_ROOT is not 21 | # /boot which may be the case if the ESP is not mounted there. 22 | # 23 | # Instead ignore what kernel-install tells us, and mirror what the -systemd 24 | # variant of this plugin does and always install to /boot 25 | KERNEL_INSTALL_ROOT="/boot" 26 | SUFFIX= 27 | elif [[ ${KERNEL_INSTALL_LAYOUT} == "efistub" ]]; then 28 | if [[ -f /etc/os-release ]]; then 29 | # shellcheck source=/dev/null 30 | . /etc/os-release 31 | elif [[ -f /usr/lib/os-release ]]; then 32 | # shellcheck source=/dev/null 33 | . /usr/lib/os-release 34 | fi 35 | 36 | # Set sane default if no or broken os-release 37 | : "${NAME:=Linux}" 38 | 39 | # For efistub layout, we relocate /boot to the ESP 40 | KERNEL_INSTALL_ROOT="${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}" 41 | # Some vendors enforce that booted EFI executables have the .efi suffix. 42 | # We also want to be able to distinguish between an UKI and a regular 43 | # kernel image with an .efi suffix. 44 | SUFFIX=".efi" 45 | else 46 | exit 0 47 | fi 48 | 49 | if [[ ${COMMAND} == add ]]; then 50 | mkdir -p "${KERNEL_INSTALL_ROOT}" || exit 1 51 | 52 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Installing kernel image for ${KERNEL_VERSION}..." 53 | cp --dereference --preserve=all "${KERNEL_IMAGE}" "${KERNEL_INSTALL_ROOT}/kernel-${KERNEL_VERSION}${SUFFIX}" || exit 1 54 | 55 | INITRD="${KERNEL_INSTALL_STAGING_AREA}/initrd" 56 | if [[ -f ${INITRD} ]]; then 57 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Installing initramfs image for ${KERNEL_VERSION}..." 58 | cp --dereference --preserve=all "${INITRD}" "${KERNEL_INSTALL_ROOT}/initramfs-${KERNEL_VERSION}.img" || exit 1 59 | fi 60 | 61 | # Copy microcode to ESP so we can add it to the efistub entry 62 | for CPU in intel amd; do 63 | if [[ -f "${KERNEL_INSTALL_STAGING_AREA}/microcode-${CPU}" ]]; then 64 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Copying microcode for ${CPU} CPU..." 65 | cp --dereference --preserve=all "${KERNEL_INSTALL_STAGING_AREA}/microcode-${CPU}" "${KERNEL_INSTALL_ROOT}/${CPU}-uc.img" || exit 1 66 | fi 67 | done 68 | elif [[ ${COMMAND} == remove ]]; then 69 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Removing kernel and initramfs image for ${KERNEL_VERSION}..." 70 | rm -f \ 71 | "${KERNEL_INSTALL_ROOT}/kernel-${KERNEL_VERSION}${SUFFIX}" \ 72 | "${KERNEL_INSTALL_ROOT}/initramfs-${KERNEL_VERSION}.img" || exit 1 73 | fi 74 | -------------------------------------------------------------------------------- /hooks/systemd/90-zz-update-static.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | BOOT_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [[ ${COMMAND} != add ]]; then 16 | exit 0 17 | fi 18 | 19 | if [[ ${KERNEL_INSTALL_LAYOUT} == "grub" || ${KERNEL_INSTALL_LAYOUT} == "compat" ]]; then 20 | # kernel-install insists on using the EFI partition as BOOT_ROOT. And ignores 21 | # the variable if it does not point to the root of a FAT partition. 22 | # This is what we want for systemd-boot, but it is definitely not what we want 23 | # for GRUB. grub-install (by default) installs a grub efi executable that 24 | # always loads /boot/grub/grub.cfg, this will break if the BOOT_ROOT is not 25 | # /boot which may be the case if the ESP is not mounted there. 26 | # 27 | # Instead ignore what kernel-install tells us, and mirror what the -systemd 28 | # variant of this plugin does and always install to /boot 29 | KERNEL_INSTALL_ROOT="/boot" 30 | SUFFIX= 31 | STATIC_KERNEL_NAME="kernel" 32 | TRIES= 33 | 34 | elif [[ ${KERNEL_INSTALL_LAYOUT} == "efistub" || ${KERNEL_INSTALL_LAYOUT} == "uki" ]]; then 35 | if [[ -f /etc/os-release ]]; then 36 | # shellcheck source=/dev/null 37 | . /etc/os-release 38 | elif [[ -f /usr/lib/os-release ]]; then 39 | # shellcheck source=/dev/null 40 | . /usr/lib/os-release 41 | fi 42 | 43 | # Set sane default if no or broken os-release 44 | : "${NAME:=Linux}" 45 | : "${ID:=linux}" 46 | 47 | # For efistub layout, we relocate /boot to the ESP 48 | if [[ ${KERNEL_INSTALL_LAYOUT} == "efistub" ]]; then 49 | KERNEL_INSTALL_ROOT="${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}" 50 | STATIC_KERNEL_NAME="kernel" 51 | TRIES= 52 | elif [[ ${KERNEL_INSTALL_LAYOUT} == "uki" ]]; then 53 | KERNEL_INSTALL_ROOT="${KERNEL_INSTALL_BOOT_ROOT}/EFI/Linux" 54 | STATIC_KERNEL_NAME="${KERNEL_INSTALL_ENTRY_TOKEN}" 55 | 56 | TRIES_FILE=${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries 57 | if [[ -f ${TRIES_FILE} ]]; then 58 | read -r TRIES <"${TRIES_FILE}" || exit 1 59 | TRIES="+${TRIES}" 60 | else 61 | TRIES= 62 | fi 63 | fi 64 | # Some vendors enforce that booted EFI executables have the .efi suffix. 65 | # We also want to be able to distinguish between an UKI and a regular 66 | # kernel image with an .efi suffix. 67 | SUFFIX=".efi" 68 | else 69 | exit 0 70 | fi 71 | 72 | if [[ -L ${KERNEL_INSTALL_ROOT}/${STATIC_KERNEL_NAME}${SUFFIX} ]]; then 73 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Updating static symlink for ${KERNEL_VERSION}..." 74 | ln -sf "${STATIC_KERNEL_NAME}-${KERNEL_VERSION}${TRIES}${SUFFIX}" \ 75 | "${KERNEL_INSTALL_ROOT}/${STATIC_KERNEL_NAME}${SUFFIX}" || exit 1 76 | if [[ -f ${KERNEL_INSTALL_ROOT}/initramfs-${KERNEL_VERSION}.img ]]; then 77 | ln -sf "initramfs-${KERNEL_VERSION}.img" \ 78 | "${KERNEL_INSTALL_ROOT}/initramfs.img" || exit 1 79 | fi 80 | elif [[ -f ${KERNEL_INSTALL_ROOT}/${STATIC_KERNEL_NAME}${SUFFIX} ]]; then 81 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo "Updating static file for ${KERNEL_VERSION}..." 82 | cp --dereference --preserve=all "${KERNEL_INSTALL_ROOT}/${STATIC_KERNEL_NAME}-${KERNEL_VERSION}${TRIES}${SUFFIX}" \ 83 | "${KERNEL_INSTALL_ROOT}/${STATIC_KERNEL_NAME}${SUFFIX}" || exit 1 84 | if [[ -f ${KERNEL_INSTALL_ROOT}/initramfs-${KERNEL_VERSION}.img ]]; then 85 | cp --dereference --preserve=all "${KERNEL_INSTALL_ROOT}/initramfs-${KERNEL_VERSION}.img" \ 86 | "${KERNEL_INSTALL_ROOT}/initramfs.img" || exit 1 87 | fi 88 | fi 89 | 90 | -------------------------------------------------------------------------------- /hooks/systemd/91-grub-mkconfig.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | BOOT_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [[ ${KERNEL_INSTALL_LAYOUT} != "grub" && ${KERNEL_INSTALL_LAYOUT} != "uki" ]]; then 16 | exit 0 17 | fi 18 | 19 | # kernel-install insists on using the EFI partition as BOOT_ROOT. And ignores 20 | # the variable if it does not point to the root of a FAT partition. 21 | # This is what we want for systemd-boot, but it is definitely not what we want 22 | # for GRUB. grub-install (by default) installs a grub efi executable that 23 | # always loads /boot/grub/grub.cfg, this will break if the BOOT_ROOT is not 24 | # /boot which may be the case if the ESP is not mounted there. 25 | # 26 | # Instead ignore what kernel-install tells us, and mirror what the -systemd 27 | # variant of this plugin does and always install to /boot 28 | KERNEL_INSTALL_BOOT_ROOT="/boot" 29 | 30 | : "${GRUB_CFG:=${KERNEL_INSTALL_BOOT_ROOT}/grub/grub.cfg}" 31 | 32 | if [[ -f /etc/os-release ]]; then 33 | # shellcheck source=/dev/null 34 | . /etc/os-release 35 | elif [[ -f /usr/lib/os-release ]]; then 36 | # shellcheck source=/dev/null 37 | . /usr/lib/os-release 38 | fi 39 | 40 | # Set sane default if no or broken os-release 41 | : "${NAME:=Linux}" 42 | 43 | # The default GRUB_LINUX_KERNEL_GLOBS from /etc/grub/10_linux expanded 44 | # with efistub dir 45 | : "${GRUB_LINUX_KERNEL_GLOBS:=" 46 | /vmlinuz-* /vmlinux-* /kernel-* 47 | /efi/EFI/${NAME}/vmlinuz-*.efi 48 | /efi/EFI/${NAME}/vmlinux-*.efi 49 | /efi/EFI/${NAME}/kernel-*.efi 50 | ${KERNEL_INSTALL_BOOT_ROOT}/vmlinuz-* 51 | ${KERNEL_INSTALL_BOOT_ROOT}/vmlinux-* 52 | ${KERNEL_INSTALL_BOOT_ROOT}/kernel-* 53 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}/vmlinuz-*.efi 54 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}/vmlinux-*.efi 55 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}/kernel-*.efi 56 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/EFI/${NAME}/vmlinuz-*.efi 57 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/EFI/${NAME}/vmlinux-*.efi 58 | ${KERNEL_INSTALL_BOOT_ROOT}/EFI/EFI/${NAME}/kernel-*.efi 59 | ${KERNEL_INSTALL_BOOT_ROOT}/efi/EFI/${NAME}/vmlinuz-*.efi 60 | ${KERNEL_INSTALL_BOOT_ROOT}/efi/EFI/${NAME}/vmlinux-*.efi 61 | ${KERNEL_INSTALL_BOOT_ROOT}/efi/EFI/${NAME}/kernel-*.efi 62 | "}" 63 | export GRUB_LINUX_KERNEL_GLOBS 64 | 65 | if [[ ${COMMAND} == add || ${COMMAND} == remove ]]; then 66 | # do nothing if somehow GRUB is not installed 67 | if ! command -v grub-mkconfig >/dev/null; then 68 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ 69 | "grub-mkconfig command not available" 70 | exit 0 71 | fi 72 | 73 | if [[ -f ${GRUB_CFG} ]]; then 74 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ 75 | "Backing up existing grub config as ${GRUB_CFG}~" 76 | cp --dereference --preserve=all "${GRUB_CFG}"{,~} || { echo "Failed to save existing config" && exit 1; } 77 | fi 78 | 79 | [[ ${KERNEL_INSTALL_VERBOSE} == 1 ]] && echo \ 80 | "Generating new GRUB config as ${GRUB_CFG}" 81 | dname="$(dirname "${GRUB_CFG}")" 82 | mkdir -p "${dname}" || { echo "Failed to mkdir ${dname}" && exit 1; } 83 | # Exit non-fatally to ensure emerge does not fail completely in containers 84 | grub-mkconfig -o "${GRUB_CFG}" || { echo "grub-mkconfig failed" && exit 0; } 85 | fi 86 | -------------------------------------------------------------------------------- /hooks/systemd/95-efistub-kernel-bootcfg.install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2034 3 | 4 | # Copyright 2023-2024 Gentoo Authors 5 | # This script is installed by sys-kernel/installkernel, it is executed by 6 | # systemd's kernel-install, NOT by the traditional installkernel. I.e. this 7 | # plugin is run when the systemd USE flag is enabled or 8 | # SYSTEMD_KERNEL_INSTALL=1 is set in the environment. 9 | 10 | COMMAND="${1}" 11 | KERNEL_VERSION="${2}" 12 | BOOT_DIR_ABS="${3}" 13 | KERNEL_IMAGE="${4}" 14 | 15 | if [ "${KERNEL_INSTALL_VERBOSE}" -gt 0 ]; then 16 | LOGLEVEL="info" 17 | else 18 | LOGLEVEL="error" 19 | fi 20 | 21 | if [[ ${KERNEL_INSTALL_LAYOUT} == "uki" ]]; then 22 | if [[ -f ${KERNEL_INSTALL_CONF_ROOT:-/etc/kernel}/tries ]]; then 23 | echo "ERROR: Boot counting not supported, but tries file exists" 24 | exit 1 25 | fi 26 | 27 | if ! command -v kernel-bootcfg >/dev/null; then 28 | echo "ERROR: kernel-bootcfg command not available" 29 | exit 1 30 | fi 31 | 32 | if command -v systemctl >/dev/null; then 33 | if [[ $(systemctl is-enabled kernel-bootcfg-boot-successful.service) != enabled ]]; then 34 | echo "ERROR: kernel-bootcfg-boot-successful service not enabled" 35 | exit 1 36 | fi 37 | else 38 | [[ "${KERNEL_INSTALL_VERBOSE}" -gt 0 ]] && echo \ 39 | "WARNING: Cannot check if kernel-bootcfg-boot-successful service is enabled" 40 | fi 41 | 42 | UKI="${KERNEL_INSTALL_BOOT_ROOT}/EFI/Linux/${KERNEL_INSTALL_ENTRY_TOKEN}-${KERNEL_VERSION}.efi" 43 | 44 | if [[ ${COMMAND} == add ]]; then 45 | if [[ ! -f ${UKI} ]]; then 46 | echo "layout=uki, but no UKI was found, exiting" 47 | exit 1 48 | fi 49 | 50 | unset PRETTY_NAME NAME VERSION_ID 51 | if [[ -f /etc/os-release ]]; then 52 | # shellcheck source=/dev/null 53 | . /etc/os-release 54 | elif [[ -f /usr/lib/os-release ]]; then 55 | # shellcheck source=/dev/null 56 | . /usr/lib/os-release 57 | fi 58 | 59 | if [[ -n "${PRETTY_NAME}" ]]; then 60 | TITLE="${PRETTY_NAME} ${KERNEL_VERSION} (UKI)" 61 | elif [[ -n "${NAME}" ]] && [[ -n "${VERSION_ID}" ]]; then 62 | TITLE="${NAME} ${VERSION_ID} ${KERNEL_VERSION} (UKI)" 63 | else 64 | TITLE="${KERNEL_INSTALL_ENTRY_TOKEN} ${KERNEL_VERSION} (UKI)" 65 | fi 66 | 67 | PARTLABEL="$(df "${UKI}" --output=source | tail -1 | xargs -r lsblk --output=PARTLABEL --noheadings)" 68 | if [[ -n ${PARTLABEL} ]]; then 69 | TITLE="${TITLE} on ${PARTLABEL}" 70 | fi 71 | 72 | [[ "${KERNEL_INSTALL_VERBOSE}" -gt 0 ]] && echo "Adding ${UKI} to UEFI boot entries..." 73 | kernel-bootcfg --loglevel "${LOGLEVEL}" --add-uki "${UKI}" --title "${TITLE}" --once || exit 1 74 | elif [[ ${COMMAND} == remove ]]; then 75 | [[ "${KERNEL_INSTALL_VERBOSE}" -gt 0 ]] && echo "Removing ${UKI} from UEFI boot entries..." 76 | kernel-bootcfg --loglevel "${LOGLEVEL}" --remove-uki "${UKI}" || exit 1 77 | fi 78 | elif [[ ${KERNEL_INSTALL_LAYOUT} == "efistub" ]]; then 79 | if ! command -v kernel-bootcfg >/dev/null; then 80 | echo "ERROR: kernel-bootcfg command not available" 81 | exit 1 82 | fi 83 | 84 | if command -v systemctl >/dev/null; then 85 | if [[ $(systemctl is-enabled kernel-bootcfg-boot-successful.service) != enabled ]]; then 86 | echo "ERROR: kernel-bootcfg-boot-successful service not enabled" 87 | exit 1 88 | fi 89 | else 90 | [[ "${KERNEL_INSTALL_VERBOSE}" -gt 0 ]] && echo \ 91 | "WARNING: Cannot check if kernel-bootcfg-boot-successful service is enabled" 92 | fi 93 | 94 | unset PRETTY_NAME NAME VERSION_ID 95 | if [[ -f /etc/os-release ]]; then 96 | # shellcheck source=/dev/null 97 | . /etc/os-release 98 | elif [[ -f /usr/lib/os-release ]]; then 99 | # shellcheck source=/dev/null 100 | . /usr/lib/os-release 101 | fi 102 | 103 | # Set sane default if no or broken os-release 104 | : "${NAME:=Linux}" 105 | 106 | KERNEL_IMAGE="${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}/kernel-${KERNEL_VERSION}.efi" 107 | INITRD="${KERNEL_INSTALL_BOOT_ROOT}/EFI/${NAME}/initramfs-${KERNEL_VERSION}.img" 108 | 109 | if [[ ${COMMAND} == add ]]; then 110 | if [[ ! -f ${KERNEL_IMAGE} ]]; then 111 | echo "No kernel image was found, exiting" 112 | exit 1 113 | fi 114 | 115 | KERNEL_BOOTCFG_ARGS=( 116 | --loglevel "${LOGLEVEL}" 117 | --once 118 | ) 119 | 120 | # From 90-loadentry.install 121 | if [[ -n "${KERNEL_INSTALL_CONF_ROOT}" ]]; then 122 | if [[ -f "${KERNEL_INSTALL_CONF_ROOT}/cmdline" ]]; then 123 | BOOT_OPTIONS="$(tr -s "${IFS}" ' ' <"${KERNEL_INSTALL_CONF_ROOT}/cmdline")" 124 | fi 125 | elif [[ -f /etc/kernel/cmdline ]]; then 126 | BOOT_OPTIONS="$(tr -s "${IFS}" ' ' "${STATE}" || exit 1 86 | echo -e "${LOGLINE}" >> "${LOG}" || exit 1 87 | -------------------------------------------------------------------------------- /installkernel: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (C) 1995 - 1998, Ian A. Murdock 4 | # Copyright (C) 1998, 1999, Guy Maor 5 | # Copyright (C) 2002, Matthew Wilcox 6 | # Copyright (C) 2002, 2004, 2005, 2007, 2009 Clint Adams 7 | # Copyright (C) 2009 Manoj Srivasta 8 | # Copyright 2020-2024 Gentoo Authors 9 | # 10 | # Install the kernel on a Linux system. 11 | # 12 | # This script is called by the kernel's "make install" if it is installed as 13 | # /sbin/installkernel. It is also called by kernel-install.eclass. 14 | 15 | : "${SYSTEMD_KERNEL_INSTALL:=0}" 16 | : "${INSTALLKERNEL_VERBOSE:=0}" 17 | _ik_install_all=0 18 | _ik_remaining_optargs= 19 | _ik_arg_index=0 20 | # Use same defaults as systemd's kernel-install 21 | _ik_arg_1="$(uname -r)" 22 | _ik_arg_2=/lib/modules/${_ik_arg_1}/vmlinuz 23 | _ik_arg_3=/lib/modules/${_ik_arg_1}/System.map 24 | _ik_arg_4=/boot 25 | # Of course, powerpc has to be all different, and passes in a fifth 26 | # argument, just because it is "special". We ignore the fifth argument, 27 | # and do not flag is as an error, which it would be for any arch apart 28 | # from powerpc 29 | _ik_arg_5= 30 | 31 | while [ ${#} -gt 0 ]; do 32 | case "${1}" in 33 | --help|-h) 34 | echo "Gentoo's helper utility to install new kernel versions" 35 | echo 36 | echo "Usage: installkernel " 37 | echo 38 | echo "Optional arguments:" 39 | echo " -h, --help: display this help text" 40 | echo " -v, --verbose: run in verbose mode and export \$INSTALLKERNEL_VERBOSE" 41 | echo " -a, --all: iteratively install all versions available in /lib/modules/" 42 | echo " --systemd, --no-systemd: offload installation to systemd's kernel-install" 43 | echo 44 | echo "Other optional arguments are passed on to systemd's kernel-install if this is enabled" 45 | echo "via the --systemd argument. The default value for --systemd|--no-systemd is controlled" 46 | echo "by the value of the \"systemd\" USE flag on the sys-kernel/installkernel package." 47 | if command -v kernel-install >/dev/null; then 48 | echo 49 | kernel-install --help 50 | fi 51 | echo 52 | echo "See the installkernel(8) man page for details." 53 | exit 0 54 | ;; 55 | --verbose|-v) 56 | INSTALLKERNEL_VERBOSE=1 57 | _ik_remaining_optargs="${_ik_remaining_optargs} ${1}" 58 | ;; 59 | --all|-a) 60 | _ik_install_all=1 61 | ;; 62 | --systemd) 63 | SYSTEMD_KERNEL_INSTALL=1 64 | ;; 65 | --no-systemd) 66 | SYSTEMD_KERNEL_INSTALL=0 67 | ;; 68 | -*) 69 | _ik_remaining_optargs="${_ik_remaining_optargs} ${1}" 70 | ;; 71 | *) 72 | _ik_arg_index=$((_ik_arg_index+1)) 73 | if [ ${_ik_arg_index} -eq 1 ]; then 74 | _ik_arg_1=${1} 75 | elif [ ${_ik_arg_index} -eq 2 ]; then 76 | _ik_arg_2=${1} 77 | elif [ ${_ik_arg_index} -eq 3 ]; then 78 | _ik_arg_3=${1} 79 | elif [ ${_ik_arg_index} -eq 4 ]; then 80 | _ik_arg_4=${1} 81 | elif [ ${_ik_arg_index} -eq 5 ]; then 82 | _ik_arg_5=${1} 83 | else 84 | echo "Too many arguments." 85 | echo "Usage: installkernel " 86 | echo " [--verbose] [--all] [--systemd|--no-systemd] [--help]" 87 | exit 1 88 | fi 89 | ;; 90 | esac 91 | shift 92 | done 93 | 94 | if [ "${SYSTEMD_KERNEL_INSTALL}" -eq 1 ] && command -v kernel-install >/dev/null 95 | then 96 | # If the ${0} of kernel-install is installkernel it takes its arguments 97 | # in the same way we do here. We could use "exec -a ${0} .. ${@}" for this, 98 | # but the -a argument is not POSIX, only bash. 99 | # TODO: maybe revisit this if we ever bashify the script. 100 | if [ ${_ik_arg_index} -le 3 ] || [ "${_ik_arg_4}" = "/boot" ]; then 101 | # kernel-install does not support relocation (ignores $4, see manual) 102 | if [ ${_ik_install_all} -eq 1 ]; then 103 | # shellcheck disable=SC2086 104 | exec kernel-install add-all ${_ik_remaining_optargs} 105 | else 106 | # shellcheck disable=SC2086 107 | exec kernel-install add ${_ik_remaining_optargs} "${_ik_arg_1}" "${_ik_arg_2}" 108 | fi 109 | else 110 | echo "WARNING: A custom installation directory is specified as fourth argument." 111 | echo "WARNING: Systemd kernel-install does not support this. Falling back" 112 | echo "WARNING: to legacy installkernel. SYSTEMD_KERNEL_INSTALL is ignored." 113 | fi 114 | fi 115 | 116 | set -e 117 | 118 | # Used to find pre and post install hooks 119 | dropindirs_sort() { 120 | for d; do 121 | for i in "${d}/"*; do 122 | [ -e "${i}" ] && echo "${i##*/}" 123 | done 124 | done | sort -Vu | while read -r f; do 125 | for d; do 126 | if [ -e "${d}/${f}" ]; then 127 | [ -x "${d}/${f}" ] && echo "${d}/${f}" 128 | continue 2 129 | fi 130 | done 131 | done 132 | } 133 | 134 | # Create backups of older versions before installing 135 | updatever() { 136 | oldsuffix="${3}.old" 137 | if [ "${3%.efi}" != "${3}" ]; then 138 | # Some UEFIs enforce .efi suffix, so if using efi files retain suffix 139 | oldsuffix="-old${3}" 140 | fi 141 | 142 | if [ -f "${dir}/${1}-${ver}${3}" ]; then 143 | # If they are hardlinked together, mv will fail. 144 | rm -f "${dir}/${1}-${ver}${oldsuffix}" 145 | mv "${dir}/${1}-${ver}${3}" "${dir}/${1}-${ver}${oldsuffix}" 146 | fi 147 | 148 | cp --dereference --preserve=all "${2}" "${dir}/${1}-${ver}${3}" 149 | 150 | # Update static version-less symlink/copy 151 | if [ -f "${dir}/${1}${3}" ] || [ -L "${dir}/${1}${3}" ]; then 152 | # The presence of "${dir}/${1}${3}" is unusual in modern installations, and 153 | # the results are mostly unused. So only recreate them if they 154 | # already existed. 155 | if [ -L "${dir}/${1}${3}" ]; then 156 | # If we were using links, continue to use links, updating if 157 | # we need to. 158 | if [ "$(readlink -f "${dir}/${1}${3}")" = "${dir}/${1}-${ver}${3}" ]; then 159 | # Yup, we need to change 160 | ln -sf "${1}-${ver}${oldsuffix}" "${dir}/${1}${oldsuffix}" 161 | else 162 | # If they are hardlinked together, mv will fail. 163 | rm -f "${dir}/${1}${oldsuffix}" 164 | mv "${dir}/${1}${3}" "${dir}/${1}${oldsuffix}" 165 | fi 166 | ln -sf "${1}-${ver}${3}" "${dir}/${1}${3}" 167 | else # No links 168 | # If they are hardlinked together, mv will fail. 169 | rm -f "${dir}/${1}${oldsuffix}" 170 | mv "${dir}/${1}${3}" "${dir}/${1}${oldsuffix}" 171 | cp --dereference --preserve=all "${2}" "${dir}/${1}${3}" 172 | fi 173 | fi 174 | } 175 | 176 | cleanup() { 177 | # shellcheck disable=SC2317 178 | if [ -n "${INSTALLKERNEL_STAGING_AREA}" ]; then 179 | rm -rf "${INSTALLKERNEL_STAGING_AREA}" 180 | fi 181 | } 182 | trap cleanup EXIT 183 | 184 | # Main installation script that we will call later 185 | main() { 186 | ver=${1:?} 187 | img=${2:?} 188 | map=${3:?} 189 | dir=${4:-/boot} 190 | if [ ${#} -gt 4 ]; then 191 | echo "Too many arguments." 192 | return 1 193 | fi 194 | 195 | INSTALLKERNEL_STAGING_AREA="$(mktemp -d -t installkernel.staging.XXXXXXX)" 196 | export INSTALLKERNEL_STAGING_AREA 197 | 198 | suffix= 199 | if [ "${INSTALLKERNEL_LAYOUT}" = "efistub" ]; then 200 | if [ ${#} -le 3 ] || [ "${4%/boot}" != "${4}" ] 201 | then 202 | # Relocate to ESP 203 | for candidate in "${dir}/EFI" "${dir}/efi" "${dir}" "${dir%/boot}/efi" 204 | do 205 | if [ -d "${candidate}/EFI/${NAME}" ]; then 206 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 207 | echo "Found vendor directory on ESP ${candidate}" 208 | fi 209 | dir=${candidate}/EFI/${NAME} 210 | suffix=.efi 211 | # backwards compatibility 212 | if [ -f "/boot/intel-uc.img" ]; then 213 | cp --dereference --preserve=all "/boot/intel-uc.img" "${dir}/intel-uc.img" 214 | fi 215 | if [ -f "/boot/amd-uc.img" ]; then 216 | cp --dereference --preserve=all "/boot/amd-uc.img" "${dir}/amd-uc.img" 217 | fi 218 | else 219 | continue 220 | fi 221 | done 222 | 223 | if [ "${dir}" = "/boot" ] || [ "${dir}" = "${4}" ] 224 | then 225 | # No vendor dir found, try to create one 226 | for candidate in "${dir}/EFI" "${dir}/efi" "${dir}" "${dir%/boot}/efi" 227 | do 228 | if [ -d "${candidate}/EFI" ]; then 229 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 230 | echo "Creating vendor directory on ESP ${candidate}" 231 | fi 232 | mkdir -p "${candidate}/EFI/${NAME}" 233 | dir=${candidate}/EFI/${NAME} 234 | suffix=.efi 235 | # backwards compatibility 236 | if [ -f "/boot/intel-uc.img" ]; then 237 | cp --dereference --preserve=all "/boot/intel-uc.img" "${dir}/intel-uc.img" 238 | fi 239 | if [ -f "/boot/amd-uc.img" ]; then 240 | cp --dereference --preserve=all "/boot/amd-uc.img" "${dir}/amd-uc.img" 241 | fi 242 | else 243 | continue 244 | fi 245 | done 246 | fi 247 | 248 | if [ "${dir}" = "/boot" ] || [ "${dir}" = "${4}" ] 249 | then 250 | # Still no vendor dir, warn and fallback 251 | echo "WARNING: layout=efistub set, but did not find vendor directory on ESP." 252 | echo "WARNING: Please create the EFI/${NAME} directory on the EFI System partition manually." 253 | fi 254 | fi 255 | fi 256 | 257 | base_dir=$(dirname "${img}") 258 | prebuilt_initrd=${base_dir}/initrd 259 | prebuilt_uki=${base_dir}/uki.efi 260 | 261 | initrd=${INSTALLKERNEL_STAGING_AREA}/initrd 262 | uki=${INSTALLKERNEL_STAGING_AREA}/uki.efi 263 | 264 | # Copy prebuilt initrd, uki.efi at kernel location 265 | if [ -f "${prebuilt_initrd}" ]; then 266 | cp --dereference --preserve=all "${prebuilt_initrd}" "${initrd}" 267 | fi 268 | if [ -f "${prebuilt_uki}" ]; then 269 | cp --dereference --preserve=all "${prebuilt_uki}" "${uki}" 270 | fi 271 | 272 | # If installing in the usual directory, run the same scripts that hook 273 | # into kernel package installation. Also make sure the PATH includes 274 | # /usr/sbin and /sbin, just as dpkg would. 275 | if [ ${#} -le 3 ] || [ "${4}" = "/boot" ] 276 | then 277 | err=0 278 | ( 279 | #shellcheck disable=SC2030 280 | export LC_ALL=C PATH="${PATH}:/usr/sbin:/sbin" 281 | 282 | if [ -z "${INSTALLKERNEL_PREINST_PLUGINS}" ]; then 283 | INSTALLKERNEL_PREINST_PLUGINS="$( 284 | dropindirs_sort \ 285 | "/etc/kernel/preinst.d" \ 286 | "/usr/lib/kernel/preinst.d" 287 | )" 288 | fi 289 | 290 | for plugin in ${INSTALLKERNEL_PREINST_PLUGINS}; do 291 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 292 | echo 293 | echo "Running ${plugin} ${ver} ${img}..." 294 | echo 295 | fi 296 | "${plugin}" "${ver}" "${img}" || exit ${?} 297 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 298 | echo 299 | echo "Hook ${plugin} finished successfully" 300 | echo 301 | fi 302 | done 303 | ) || err=${?} 304 | [ ${err} -eq 77 ] && return 0 305 | [ ${err} -ne 0 ] && return ${err} 306 | else 307 | echo "WARNING: A custom installation directory is specified as fourth argument." 308 | echo "WARNING: In this configuration running installation hooks is not supported." 309 | echo "WARNING: All pre-installation hooks are ignored." 310 | fi 311 | 312 | if [ "${img%vmlinux*}" != "${img}" ]; then 313 | img_dest=vmlinux 314 | else 315 | img_dest=vmlinuz 316 | fi 317 | 318 | # If we found a uki.efi, install it instead of kernel+initrd 319 | if [ -f "${uki}" ] && [ "${INSTALLKERNEL_LAYOUT}" = "uki" ]; then 320 | suffix=.efi 321 | if [ ${#} -le 3 ] || [ "${4%/boot}" != "${4}" ] 322 | then 323 | # Relocate to ESP 324 | for candidate in "${dir}/EFI" "${dir}/efi" "${dir}" "${dir%/boot}/efi" 325 | do 326 | if [ -d "${candidate}/EFI/Linux" ]; then 327 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 328 | echo "Found UKI directory on ESP ${candidate}" 329 | fi 330 | dir=${candidate}/EFI/Linux 331 | img_dest=${ID} 332 | else 333 | continue 334 | fi 335 | done 336 | 337 | if [ "${dir}" = "/boot" ] || [ "${dir}" = "${4}" ] 338 | then 339 | # No UKI dir found, try to create one 340 | for candidate in "${dir}/EFI" "${dir}/efi" "${dir}" "${dir%/boot}/efi" 341 | do 342 | if [ -d "${candidate}/EFI" ]; then 343 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 344 | echo "Creating UKI directory on ESP ${candidate}" 345 | fi 346 | mkdir -p "${candidate}/EFI/Linux" 347 | dir=${candidate}/EFI/Linux 348 | img_dest=${ID} 349 | else 350 | continue 351 | fi 352 | done 353 | fi 354 | 355 | if [ "${dir}" = "/boot" ] || [ "${dir}" = "${4}" ] 356 | then 357 | # Still no UKI dir, warn and fallback 358 | echo "WARNING: layout=uki set, but did not find the UKI directory on ESP" 359 | echo "WARNING: Please create the EFI/Linux directory on the EFI System partition manually" 360 | fi 361 | fi 362 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 363 | echo "Installing Unified Kernel Image for ${ver}..." 364 | fi 365 | updatever "${img_dest}" "${uki}" "${suffix}" 366 | else 367 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 368 | echo "Installing kernel image for ${ver}..." 369 | fi 370 | updatever "${img_dest}" "${img}" "${suffix}" 371 | if [ -f "${initrd}" ]; then 372 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 373 | echo "Installing initramfs image for ${ver}..." 374 | fi 375 | updatever initramfs "${initrd}" .img 376 | fi 377 | 378 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 379 | echo "Installing System.map for ${ver}..." 380 | fi 381 | updatever System.map "${map}" 382 | 383 | basedir=$(dirname "${map}") 384 | if [ -f "${basedir}/.config" ]; then 385 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 386 | echo "Installing config for ${ver}..." 387 | fi 388 | updatever config "${basedir}/.config" 389 | elif [ -f "${basedir}/config" ]; then 390 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 391 | echo "Installing config for ${ver}..." 392 | fi 393 | updatever config "${basedir}/config" 394 | fi 395 | fi 396 | 397 | # If installing in the usual directory, run the same scripts that hook 398 | # into kernel package installation. Also make sure the PATH includes 399 | # /usr/sbin and /sbin, just as dpkg would. 400 | if [ ${#} -le 3 ] || [ "${4}" = "/boot" ] 401 | then 402 | err=0 403 | ( 404 | #shellcheck disable=SC2031 405 | export LC_ALL=C PATH="${PATH}:/usr/sbin:/sbin" 406 | 407 | if [ -z "${INSTALLKERNEL_POSTINST_PLUGINS}" ]; then 408 | INSTALLKERNEL_POSTINST_PLUGINS="$( 409 | dropindirs_sort \ 410 | "/etc/kernel/postinst.d" \ 411 | "/usr/lib/kernel/postinst.d" 412 | )" 413 | fi 414 | 415 | for plugin in ${INSTALLKERNEL_POSTINST_PLUGINS}; do 416 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 417 | echo 418 | echo "Running ${plugin} ${ver} ${dir}/${img_dest}-${ver}${suffix}..." 419 | echo 420 | fi 421 | "${plugin}" "${ver}" "${dir}/${img_dest}-${ver}${suffix}" || exit ${?} 422 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 423 | echo 424 | echo "Hook ${plugin} finished successfully" 425 | echo 426 | fi 427 | done 428 | ) || err=${?} 429 | [ ${err} -eq 77 ] && return 0 430 | [ ${err} -ne 0 ] && return ${err} 431 | else 432 | echo "WARNING: A custom installation directory is specified as fourth argument." 433 | echo "WARNING: In this configuration running installation hooks is not supported." 434 | echo "WARNING: All post-installation hooks are ignored." 435 | fi 436 | 437 | return 0 438 | } 439 | 440 | # Find and read the install.conf 441 | if [ -n "${INSTALLKERNEL_CONF_ROOT}" ]; then 442 | install_conf="${INSTALLKERNEL_CONF_ROOT}/install.conf" 443 | elif [ -f /etc/kernel/install.conf ]; then 444 | install_conf=/etc/kernel/install.conf 445 | elif [ -f /run/kernel/install.conf ]; then 446 | install_conf=/run/kernel/install.conf 447 | elif [ -f /usr/local/lib/kernel/install.conf ]; then 448 | install_conf=/usr/local/lib/kernel/install.conf 449 | elif [ -f /usr/lib/kernel/install.conf ]; then 450 | install_conf=/usr/lib/kernel/install.conf 451 | else 452 | install_conf= 453 | fi 454 | 455 | if [ -f "${install_conf}" ]; then 456 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 457 | echo "Reading ${install_conf}..." 458 | fi 459 | # shellcheck source=/dev/null 460 | . "${install_conf}" 461 | 462 | if [ -n "${layout}" ]; then 463 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 464 | echo "${install_conf} configures layout=${layout}" 465 | fi 466 | if [ -z "${INSTALLKERNEL_LAYOUT}" ]; then 467 | INSTALLKERNEL_LAYOUT="${layout}" 468 | fi 469 | fi 470 | if [ -n "${initrd_generator}" ]; then 471 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 472 | echo "${install_conf} configures initrd_generator=${initrd_generator}" 473 | fi 474 | if [ -z "${INSTALLKERNEL_INITRD_GENERATOR}" ]; then 475 | INSTALLKERNEL_INITRD_GENERATOR="${initrd_generator}" 476 | fi 477 | fi 478 | if [ -n "${uki_generator}" ]; then 479 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 480 | echo "${install_conf} configures uki_generator=${uki_generator}" 481 | fi 482 | if [ -z "${INSTALLKERNEL_UKI_GENERATOR}" ]; then 483 | INSTALLKERNEL_UKI_GENERATOR="${uki_generator}" 484 | fi 485 | fi 486 | fi 487 | 488 | export INSTALLKERNEL_LAYOUT 489 | export INSTALLKERNEL_INITRD_GENERATOR 490 | export INSTALLKERNEL_UKI_GENERATOR 491 | export INSTALLKERNEL_VERBOSE 492 | 493 | if [ -f /etc/os-release ]; then 494 | # shellcheck source=/dev/null 495 | . /etc/os-release 496 | elif [ -f /usr/lib/os-release ]; then 497 | # shellcheck source=/dev/null 498 | . /usr/lib/os-release 499 | fi 500 | 501 | # Set sane default if no or broken os-release 502 | export NAME="${NAME:=Linux}" 503 | export ID="${ID:=linux}" 504 | export PRETTY_NAME="${PRETTY_NAME:=Linux}" 505 | 506 | # Now we actually run the install 507 | main_err=0 508 | if [ ${_ik_install_all} -eq 1 ]; then 509 | for ver in /lib/modules/*; do 510 | ver=$(basename "${ver}") 511 | img=/lib/modules/${ver}/vmlinuz 512 | map=/lib/modules/${ver}/System.map 513 | if [ -f "${img}" ] && [ -f "${map}" ]; then 514 | main "${ver}" "${img}" "${map}" "${_ik_arg_4}" || 515 | { main_err=${?}; echo "WARNING: Installing ${ver} failed"; } 516 | cleanup 517 | else 518 | if [ "${INSTALLKERNEL_VERBOSE}" -gt 0 ]; then 519 | echo "WARNING: Skipping ${ver}, no kernel image or system map available." 520 | fi 521 | fi 522 | done 523 | else 524 | if [ -f "${_ik_arg_2}" ] && [ -f "${_ik_arg_3}" ]; then 525 | main "${_ik_arg_1}" "${_ik_arg_2}" "${_ik_arg_3}" "${_ik_arg_4}" || 526 | { main_err=${?}; echo "ERROR: Installing ${_ik_arg_1} failed"; } 527 | cleanup 528 | else 529 | echo "ERROR: No such kernel image or system map." 530 | exit 1 531 | fi 532 | fi 533 | 534 | exit ${main_err} 535 | -------------------------------------------------------------------------------- /installkernel-9999.ebuild: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2025 Gentoo Authors 2 | # Distributed under the terms of the GNU General Public License v2 3 | 4 | EAPI=8 5 | 6 | inherit eapi9-ver linux-info 7 | 8 | DESCRIPTION="Gentoo fork of installkernel script from debianutils" 9 | HOMEPAGE=" 10 | https://github.com/projg2/installkernel-gentoo 11 | https://wiki.gentoo.org/wiki/Installkernel 12 | " 13 | SRC_URI="https://github.com/projg2/installkernel-gentoo/archive/v${PV}.tar.gz 14 | -> ${P}.tar.gz" 15 | S="${WORKDIR}/${PN}-gentoo-${PV}" 16 | 17 | LICENSE="GPL-2+" 18 | SLOT="0" 19 | KEYWORDS="~alpha ~amd64 ~arm ~arm64 ~hppa ~loong ~m68k ~mips ~ppc ~ppc64 ~riscv ~s390 ~sparc ~x86 ~amd64-linux ~x86-linux" 20 | IUSE="dracut efistub grub refind systemd systemd-boot ugrd uki ukify" 21 | REQUIRED_USE=" 22 | systemd-boot? ( systemd ) 23 | ukify? ( uki ) 24 | ?? ( dracut ugrd ) 25 | " 26 | # systemd-boot could be made to work without the systemd flag, but this 27 | # makes no sense since in systemd(-utils) the boot flag already 28 | # requires the kernel-install flag. 29 | # 30 | # Ukify hooks do nothing if the layout is not uki, so force this here. 31 | # 32 | # Only one initramfs generator flag can be selected. Note that while 33 | # both dracut and ukify are UKI generators we don't block those because 34 | # enabling both results in building an initramfs only with dracut and 35 | # building an UKI with ukify, which is a valid configuration. 36 | 37 | RDEPEND=" 38 | !<=sys-kernel/installkernel-systemd-3 39 | dracut? ( 40 | >=sys-kernel/dracut-106 41 | uki? ( 42 | || ( 43 | sys-apps/systemd[boot(-)] 44 | sys-apps/systemd-utils[boot(-)] 45 | ) 46 | ) 47 | ) 48 | efistub? ( 49 | systemd? ( >=app-emulation/virt-firmware-24.7 ) 50 | !systemd? ( sys-boot/uefi-mkconfig ) 51 | ) 52 | grub? ( sys-boot/grub ) 53 | refind? ( sys-boot/refind ) 54 | systemd? ( 55 | || ( 56 | >=sys-apps/systemd-255[kernel-install(-)] 57 | >=sys-apps/systemd-utils-255[kernel-install(-)] 58 | ) 59 | ) 60 | systemd-boot? ( 61 | || ( 62 | sys-apps/systemd[boot(-)] 63 | sys-apps/systemd-utils[boot(-)] 64 | ) 65 | ) 66 | ukify? ( 67 | || ( 68 | sys-apps/systemd[boot(-),ukify(-)] 69 | sys-apps/systemd-utils[boot(-),ukify(-)] 70 | ) 71 | ) 72 | ugrd? ( >=sys-kernel/ugrd-1.31.2 ) 73 | !=sys-apps/systemd-255.2-r1 74 | !=sys-apps/systemd-255.2-r0 75 | !~sys-apps/systemd-255.1 76 | !~sys-apps/systemd-255.0 77 | !=sys-apps/systemd-254.8-r0 78 | !=sys-apps/systemd-254.7-r0 79 | !~sys-apps/systemd-254.6 80 | !<=sys-apps/systemd-254.5-r1 81 | " # Block against systemd that still installs dummy install.conf 82 | 83 | pkg_setup() { 84 | use efistub && CONFIG_CHECK="~EFI_STUB" linux-info_pkg_setup 85 | } 86 | 87 | src_install() { 88 | keepdir /etc/kernel/install.d 89 | keepdir /etc/kernel/preinst.d 90 | keepdir /etc/kernel/postinst.d 91 | keepdir /usr/lib/kernel/install.d 92 | keepdir /usr/lib/kernel/preinst.d 93 | keepdir /usr/lib/kernel/postinst.d 94 | 95 | exeinto /usr/lib/kernel/preinst.d 96 | doexe hooks/99-check-diskspace.install 97 | use dracut && doexe hooks/50-dracut.install 98 | use ukify && doexe hooks/60-ukify.install 99 | 100 | exeinto /usr/lib/kernel/postinst.d 101 | doexe hooks/99-write-log.install 102 | use grub && doexe hooks/91-grub-mkconfig.install 103 | use efistub && doexe hooks/95-efistub-uefi-mkconfig.install 104 | use refind && doexe hooks/95-refind-copy-icon.install 105 | 106 | exeinto /usr/lib/kernel/install.d 107 | doexe hooks/systemd/00-00machineid-directory.install 108 | doexe hooks/systemd/10-copy-prebuilt.install 109 | doexe hooks/systemd/85-check-diskspace.install 110 | doexe hooks/systemd/90-compat.install 111 | doexe hooks/systemd/90-zz-update-static.install 112 | doexe hooks/systemd/99-write-log.install 113 | use grub && doexe hooks/systemd/91-grub-mkconfig.install 114 | use efistub && doexe hooks/systemd/95-efistub-kernel-bootcfg.install 115 | use refind && doexe hooks/systemd/95-refind-copy-icon.install 116 | 117 | if use grub && use uki; then 118 | exeinto /etc/grub.d 119 | doexe grub/05_uki 120 | fi 121 | 122 | if use systemd; then 123 | sed -e 's/${SYSTEMD_KERNEL_INSTALL:=0}/${SYSTEMD_KERNEL_INSTALL:=1}/g' -i installkernel || 124 | die "enabling systemd's kernel-install failed" 125 | fi 126 | 127 | # set some default config using the flags we have anyway 128 | touch "${T}/install.conf" || die 129 | echo "# This file is managed by ${CATEGORY}/${PN}" >> "${T}/install.conf" || die 130 | if use uki; then 131 | echo "layout=uki" >> "${T}/install.conf" || die 132 | elif use efistub; then 133 | echo "layout=efistub" >> "${T}/install.conf" || die 134 | elif use grub; then 135 | echo "layout=grub" >> "${T}/install.conf" || die 136 | elif use systemd-boot; then 137 | echo "layout=bls" >> "${T}/install.conf" || die 138 | else 139 | echo "layout=compat" >> "${T}/install.conf" || die 140 | fi 141 | 142 | if use dracut; then 143 | echo "initrd_generator=dracut" >> "${T}/install.conf" || die 144 | if ! use ukify; then 145 | if use uki; then 146 | echo "uki_generator=dracut" >> "${T}/install.conf" || die 147 | else 148 | echo "uki_generator=none" >> "${T}/install.conf" || die 149 | fi 150 | fi 151 | elif use ugrd; then 152 | echo "initrd_generator=ugrd" >> "${T}/install.conf" || die 153 | else 154 | echo "initrd_generator=none" >> "${T}/install.conf" || die 155 | fi 156 | 157 | if use ukify; then 158 | echo "uki_generator=ukify" >> "${T}/install.conf" || die 159 | else 160 | if ! use dracut; then 161 | echo "uki_generator=none" >> "${T}/install.conf" || die 162 | fi 163 | fi 164 | 165 | insinto /usr/lib/kernel 166 | doins "${T}/install.conf" 167 | 168 | insinto /etc/logrotate.d 169 | newins installkernel.logrotate installkernel 170 | keepdir /var/lib/misc 171 | 172 | into / 173 | dosbin installkernel 174 | doman installkernel.8 175 | 176 | einstalldocs 177 | } 178 | 179 | pkg_postinst() { 180 | # show only when upgrading to 14+ 181 | if ver_replacing -lt 14; then 182 | elog "Version 14 and up of ${PN} effectively merges" 183 | elog "${PN}-gentoo and ${PN}-systemd." 184 | elog "Switching between the traditional installkernel and systemd's" 185 | elog "kernel-install is controlled with the systemd USE flag or the" 186 | elog "SYSTEMD_KERNEL_INSTALL environment variable." 187 | elog 188 | elog "See the installkernel wiki page[1] for more details." 189 | elog 190 | elog "[1]: https://wiki.gentoo.org/wiki/Installkernel" 191 | elog 192 | fi 193 | 194 | # show only on first install of version 20+ 195 | if [[ -z "${REPLACING_VERSIONS}" ]] || ver_replacing -lt 20; then 196 | if has_version "sys-boot/grub" && ! use grub; then 197 | elog "sys-boot/grub is installed but the grub USE flag is not enabled." 198 | elog "Users may want to enable this flag to automatically update the" 199 | elog "bootloader configuration on each kernel install." 200 | fi 201 | if ( has_version "sys-apps/systemd[boot]" || 202 | has_version "sys-apps/systemd-utils[boot]" ) && 203 | ! use systemd-boot; then 204 | elog "systemd-boot is installed but the systemd-boot USE flag" 205 | elog "is not enabled. Users should enable this flag to install kernels" 206 | elog "in a layout that systemd-boot understands and to automatically" 207 | elog "update systemd-boot's configuration on each kernel install." 208 | fi 209 | fi 210 | 211 | if use efistub; then 212 | ewarn "Automated EFI Stub booting is highly experimental. UEFI implementations" 213 | ewarn "often differ between vendors and as a result EFI stub booting is not" 214 | ewarn "guaranteed to work for all UEFI systems. Ensure an alternative method" 215 | ewarn "of booting the system is available before rebooting." 216 | fi 217 | 218 | # Initialize log file if there is none 219 | dodir /var/log 220 | local log=${ROOT}/var/log/installkernel.log 221 | if [[ ! -s ${log} ]]; then 222 | echo -e \ 223 | "DATE\t"\ 224 | "KI_VENDOR\t"\ 225 | "VERSION\t"\ 226 | "CONF_ROOT\t"\ 227 | "LAYOUT\t"\ 228 | "INITRD_GEN\t"\ 229 | "UKI_GEN\t"\ 230 | "BOOT_ROOT\t"\ 231 | "KERNEL_REL_PATH\t"\ 232 | "INITRD_REL_PATH\t"\ 233 | "PLUGIN_OVERRIDE\t"\ 234 | >> "${log}" || die 235 | fi 236 | } 237 | -------------------------------------------------------------------------------- /installkernel.8: -------------------------------------------------------------------------------- 1 | .TH INSTALLKERNEL 8 "2019-12-06" "Gentoo Linux" 2 | .SH NAME 3 | installkernel \- install a new kernel image 4 | .SH SYNOPSIS 5 | .BI "installkernel " "version kernel System.map [directory] [--verbose] [--all] [--systemd|--no-systemd]" 6 | .SH DESCRIPTION 7 | .PP 8 | .B installkernel 9 | installs a new kernel image onto the system from the Linux source 10 | tree. It is called by the Linux kernel makefiles when 11 | .B make install 12 | is invoked there, and also by portage when distribution kernels are installed. 13 | .P 14 | If an unified kernel image was generated, it is installed as 15 | .IR {directory}/vmlinuz-{version}.efi . 16 | Otherwise, the new kernel is installed into 17 | .IR {directory}/vmlinuz-{version} . 18 | If a symbolic link 19 | .I {directory}/vmlinuz 20 | already exists, it is refreshed by making a link from 21 | .I {directory}/vmlinuz 22 | to the new kernel, and the previously installed kernel is available as 23 | .IR {directory}/vmlinuz.old . 24 | .P 25 | In addition to that, 26 | .I System.map 27 | passed on the command-line is installed using the same logic. 28 | If the directory containing 29 | .I System.map 30 | contains 31 | .I .config 32 | or 33 | .I config 34 | file, it is also installed. If the directory containing the kernel image 35 | contains an 36 | .I initrd 37 | file, it is also installed. 38 | .P 39 | Kernel installs are logged to 40 | .IR /var/log/installkernel.log 41 | in a tab separated file containing the columns: 42 | DATE, KI_VENDOR, VERSION, CONF_ROOT, LAYOUT, INITRD_GEN, UKI_GEN, BOOT_ROOT, KERNEL_REL_PATH, INITRD_REL_PATH and PLUGIN_OVERRIDE. 43 | .P 44 | When the 45 | .I version, 46 | .I kernel, 47 | and/or 48 | .I System.map 49 | positional arguments are not 50 | given then these values default to the currently running kernel. Meaning 51 | that version defaults to the value of 52 | .I uname -r 53 | and the kernel image defaults to 54 | .I /lib/modules/$(uname -r)/vmlinuz 55 | and the System.map defaults to 56 | .I /lib/modules/$(uname -r)/System.map. 57 | The fourth positional argument for the installation directory defaults to 58 | .I /boot. 59 | .P 60 | If systemd's kernel-install is present on the system and the environment 61 | variable 62 | .B SYSTEMD_KERNEL_INSTALL 63 | is set to 1 or the --systemd argument is given, then kernel-install is called 64 | to install the kernel instead of this script. Any extra arguments given to 65 | installkernel are passed on to kernel-install. The default setting for this 66 | environment variable is controlled by the installkernel ebuild. When kernel 67 | installation is delegated to systemd's kernel-install this manual is not 68 | applicable. See the kernel-install manual for more information. Systemd's 69 | kernel-install supports various different layouts, the default "compat" layout 70 | is similar, but not identical, to the layout used by this installkernel. The 71 | locations of plugin scripts, as well as recognized environment variables, are 72 | also different. 73 | .P 74 | The 75 | .I --all 76 | argument may be used to iteratively install all kernel versions found 77 | under 78 | .I /lib/modules. 79 | When 80 | .I --all 81 | is combined with 82 | .I --systemd 83 | then systemd's kernel-install is called with the 84 | .I add-all 85 | operator instead of the 86 | .I 87 | add 88 | operator. 89 | 90 | .SH BUGS 91 | installkernel resides in /sbin only because the Linux kernel makefiles 92 | call it from there. It should really be in /usr/sbin. It isn't 93 | needed to boot a system. 94 | .SH PLUGINS 95 | Custom preinst and postinst plugin scripts may be installed into 96 | .IR /etc/kernel/preinst.d 97 | and 98 | .IR /etc/kernel/postinst.d. 99 | Plugins provided by packages should be installed into 100 | .IR /usr/lib/kernel/preinst.d 101 | and 102 | .IR /usr/lib/kernel/postinst.d 103 | instead. 104 | Plugin scripts that generate an initramfs should install the generated 105 | initramfs, named "initrd", in the same location as the kernel image. Plugin 106 | scripts that generate an unified kernel image should install the generated UKI, 107 | named "uki.efi", in the same location as the kernel image. 108 | The environment variables 109 | .B INSTALLKERNEL_PREINST_PLUGINS 110 | and 111 | .B INSTALLKERNEL_POSTINST_PLUGINS 112 | may be used to provide a custom list of plugin scripts to execute 113 | .P 114 | The settings 115 | .RS 116 | .IP \(bu (bullet) 117 | layout 118 | .IP \(bu (bullet) 119 | initrd_generator 120 | .IP \(bu (bullet) 121 | uki_generator 122 | .RE 123 | are read from one of these locations 124 | .IR /etc/kernel/install.conf 125 | .IR /run/kernel/install.conf 126 | .IR /usr/local/lib/kernel/install.conf 127 | .IR /usr/lib/kernel/install.conf 128 | , where the first available file is used. And exposed to the plugins 129 | as: 130 | .RS 131 | .IP \(bu (bullet) 132 | INSTALLKERNEL_LAYOUT 133 | .IP \(bu (bullet) 134 | INSTALLKERNEL_INITRD_GENERATOR 135 | .IP \(bu (bullet) 136 | INSTALLKERNEL_UKI_GENERATOR 137 | .RE 138 | respectively. If the environment variable 139 | .B INSTALLKERNEL_CONF_ROOT 140 | is set, then the install.conf at this location is used instead. 141 | -------------------------------------------------------------------------------- /installkernel.logrotate: -------------------------------------------------------------------------------- 1 | /var/log/installkernel.log { 2 | delaycompress 3 | create 4 | missingok 5 | notifempty 6 | postrotate 7 | head -n1 $2 >> $1 8 | tail -n1 $2 >> $1 9 | endscript 10 | } 11 | -------------------------------------------------------------------------------- /run_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | #shellcheck disable=SC2115 3 | 4 | cd /tmp || exit 1 5 | 6 | cp /tmp/installkernel-gentoo-9999/installkernel-9999.ebuild /var/db/repos/gentoo/sys-kernel/installkernel/installkernel-9999.ebuild || exit 1 7 | tar -czf /var/cache/distfiles/installkernel-9999.tar.gz installkernel-gentoo-9999/. || exit 1 8 | ebuild /var/db/repos/gentoo/sys-kernel/installkernel/installkernel-9999.ebuild manifest || exit 1 9 | 10 | INST_KERN="$(ls /boot/kernel*-gentoo-dist* || exit 1)" 11 | INST_KV_FULL="${INST_KERN#/boot/kernel-}" 12 | INST_KV="${INST_KV_FULL%-gentoo-dist}" 13 | 14 | # Create a fake ESP 15 | dd if=/dev/zero of=/fake-efi bs=1024 count=204800 || exit 1 16 | FAKE_EFI="$(losetup -f)" 17 | losetup "${FAKE_EFI}" /fake-efi || exit 1 18 | mkfs.vfat -F 32 "${FAKE_EFI}" || exit 1 19 | mkdir -p /efi || exit 1 20 | mount -t vfat "${FAKE_EFI}" /efi || exit 1 21 | 22 | # Generate with: 23 | # 24 | # import itertools 25 | # 26 | # for i in itertools.product(['-',''],repeat=7): 27 | # print(f"TEST_CASES[\"{i[0]}generic-uki {i[1]}dracut {i[2]}systemd {i[3]}systemd-boot {i[4]}uki {i[5]}ukify {i[6]}grub\"]=\\") 28 | # 29 | # And manually filter nonsense configurations: 30 | # - generic-uki at the same time as dracut and/or ukify 31 | # - systemd-boot without systemd 32 | # - uki without dracut or ukify 33 | declare -A TEST_CASES 34 | 35 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot -uki -ukify -grub -refind"]=\ 36 | "/boot 37 | /boot/System.map-${INST_KV}-gentoo-dist 38 | /boot/config-${INST_KV}-gentoo-dist 39 | /boot/vmlinuz-${INST_KV}-gentoo-dist 40 | /efi 41 | /efi/EFI 42 | 43 | 3 directories, 3 files" 44 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot -uki -ukify grub -refind"]=\ 45 | "/boot 46 | /boot/System.map-${INST_KV}-gentoo-dist 47 | /boot/config-${INST_KV}-gentoo-dist 48 | /boot/grub 49 | /boot/vmlinuz-${INST_KV}-gentoo-dist 50 | /efi 51 | /efi/EFI 52 | 53 | 4 directories, 3 files" 54 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot uki ukify -grub -refind"]=\ 55 | "/boot 56 | /efi 57 | /efi/EFI 58 | /efi/EFI/Linux 59 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 60 | 61 | 3 directories, 1 file" 62 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot uki ukify grub -refind"]=\ 63 | "/boot 64 | /boot/grub 65 | /efi 66 | /efi/EFI 67 | /efi/EFI/Linux 68 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 69 | 70 | 5 directories, 1 file" 71 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot -uki -ukify -grub -refind"]=\ 72 | "/boot 73 | /boot/kernel-${INST_KV}-gentoo-dist 74 | /efi 75 | /efi/EFI 76 | 77 | 3 directories, 1 file" 78 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot -uki -ukify grub -refind"]=\ 79 | "/boot 80 | /boot/grub 81 | /boot/kernel-${INST_KV}-gentoo-dist 82 | /efi 83 | /efi/EFI 84 | 85 | 4 directories, 1 file" 86 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot uki ukify -grub -refind"]=\ 87 | "/boot 88 | /efi 89 | /efi/EFI 90 | /efi/EFI/Linux 91 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 92 | 93 | 3 directories, 1 file" 94 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot uki ukify grub -refind"]=\ 95 | "/boot 96 | /boot/grub 97 | /efi 98 | /efi/EFI 99 | /efi/EFI/Linux 100 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 101 | 102 | 5 directories, 1 file" 103 | TEST_CASES["-generic-uki -dracut systemd systemd-boot -uki -ukify -grub -refind"]=\ 104 | "/boot 105 | /efi 106 | /efi/EFI 107 | /efi/gentoo 108 | /efi/gentoo/${INST_KV}-gentoo-dist 109 | /efi/gentoo/${INST_KV}-gentoo-dist/linux 110 | /efi/loader 111 | /efi/loader/entries 112 | /efi/loader/entries/gentoo-${INST_KV}-gentoo-dist.conf 113 | 114 | 6 directories, 2 files" 115 | TEST_CASES["-generic-uki -dracut systemd systemd-boot uki ukify -grub -refind"]=\ 116 | "/boot 117 | /efi 118 | /efi/EFI 119 | /efi/EFI/Linux 120 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 121 | 122 | 3 directories, 1 file" 123 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot -uki -ukify -grub -refind"]=\ 124 | "/boot 125 | /boot/System.map-${INST_KV}-gentoo-dist 126 | /boot/config-${INST_KV}-gentoo-dist 127 | /boot/initramfs-${INST_KV}-gentoo-dist.img 128 | /boot/vmlinuz-${INST_KV}-gentoo-dist 129 | /efi 130 | /efi/EFI 131 | 132 | 3 directories, 4 files" 133 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot -uki -ukify grub -refind"]=\ 134 | "/boot 135 | /boot/System.map-${INST_KV}-gentoo-dist 136 | /boot/config-${INST_KV}-gentoo-dist 137 | /boot/grub 138 | /boot/initramfs-${INST_KV}-gentoo-dist.img 139 | /boot/vmlinuz-${INST_KV}-gentoo-dist 140 | /efi 141 | /efi/EFI 142 | 143 | 4 directories, 4 files" 144 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot uki -ukify -grub -refind"]=\ 145 | "/boot 146 | /efi 147 | /efi/EFI 148 | /efi/EFI/Linux 149 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 150 | 151 | 3 directories, 1 file" 152 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot uki -ukify grub -refind"]=\ 153 | "/boot 154 | /boot/grub 155 | /efi 156 | /efi/EFI 157 | /efi/EFI/Linux 158 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 159 | 160 | 5 directories, 1 file" 161 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot uki ukify -grub -refind"]=\ 162 | "/boot 163 | /efi 164 | /efi/EFI 165 | /efi/EFI/Linux 166 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 167 | 168 | 3 directories, 1 file" 169 | TEST_CASES["-generic-uki dracut -systemd -systemd-boot uki ukify grub -refind"]=\ 170 | "/boot 171 | /boot/grub 172 | /efi 173 | /efi/EFI 174 | /efi/EFI/Linux 175 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 176 | 177 | 5 directories, 1 file" 178 | TEST_CASES["-generic-uki dracut systemd -systemd-boot -uki -ukify -grub -refind"]=\ 179 | "/boot 180 | /boot/initramfs-${INST_KV}-gentoo-dist.img 181 | /boot/kernel-${INST_KV}-gentoo-dist 182 | /efi 183 | /efi/EFI 184 | 185 | 3 directories, 2 files" 186 | TEST_CASES["-generic-uki dracut systemd -systemd-boot -uki -ukify grub -refind"]=\ 187 | "/boot 188 | /boot/grub 189 | /boot/initramfs-${INST_KV}-gentoo-dist.img 190 | /boot/kernel-${INST_KV}-gentoo-dist 191 | /efi 192 | /efi/EFI 193 | 194 | 4 directories, 2 files" 195 | TEST_CASES["-generic-uki dracut systemd -systemd-boot uki -ukify -grub -refind"]=\ 196 | "/boot 197 | /efi 198 | /efi/EFI 199 | /efi/EFI/Linux 200 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 201 | 202 | 3 directories, 1 file" 203 | TEST_CASES["-generic-uki dracut systemd -systemd-boot uki -ukify grub -refind"]=\ 204 | "/boot 205 | /boot/grub 206 | /efi 207 | /efi/EFI 208 | /efi/EFI/Linux 209 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 210 | 211 | 5 directories, 1 file" 212 | TEST_CASES["-generic-uki dracut systemd -systemd-boot uki ukify -grub -refind"]=\ 213 | "/boot 214 | /efi 215 | /efi/EFI 216 | /efi/EFI/Linux 217 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 218 | 219 | 3 directories, 1 file" 220 | TEST_CASES["-generic-uki dracut systemd -systemd-boot uki ukify grub -refind"]=\ 221 | "/boot 222 | /boot/grub 223 | /efi 224 | /efi/EFI 225 | /efi/EFI/Linux 226 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 227 | 228 | 5 directories, 1 file" 229 | TEST_CASES["-generic-uki dracut systemd systemd-boot -uki -ukify -grub -refind"]=\ 230 | "/boot 231 | /efi 232 | /efi/EFI 233 | /efi/gentoo 234 | /efi/gentoo/${INST_KV}-gentoo-dist 235 | /efi/gentoo/${INST_KV}-gentoo-dist/initrd 236 | /efi/gentoo/${INST_KV}-gentoo-dist/linux 237 | /efi/loader 238 | /efi/loader/entries 239 | /efi/loader/entries/gentoo-${INST_KV}-gentoo-dist.conf 240 | 241 | 6 directories, 3 files" 242 | TEST_CASES["-generic-uki dracut systemd systemd-boot uki -ukify -grub -refind"]=\ 243 | "/boot 244 | /efi 245 | /efi/EFI 246 | /efi/EFI/Linux 247 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 248 | 249 | 3 directories, 1 file" 250 | TEST_CASES["-generic-uki dracut systemd systemd-boot uki ukify -grub -refind"]=\ 251 | "/boot 252 | /efi 253 | /efi/EFI 254 | /efi/EFI/Linux 255 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 256 | 257 | 3 directories, 1 file" 258 | TEST_CASES["generic-uki -dracut -systemd -systemd-boot -uki -ukify -grub -refind"]=\ 259 | "/boot 260 | /boot/System.map-${INST_KV}-gentoo-dist 261 | /boot/config-${INST_KV}-gentoo-dist 262 | /boot/initramfs-${INST_KV}-gentoo-dist.img 263 | /boot/vmlinuz-${INST_KV}-gentoo-dist 264 | /efi 265 | /efi/EFI 266 | 267 | 3 directories, 4 files" 268 | TEST_CASES["generic-uki -dracut -systemd -systemd-boot -uki -ukify grub -refind"]=\ 269 | "/boot 270 | /boot/System.map-${INST_KV}-gentoo-dist 271 | /boot/config-${INST_KV}-gentoo-dist 272 | /boot/grub 273 | /boot/initramfs-${INST_KV}-gentoo-dist.img 274 | /boot/vmlinuz-${INST_KV}-gentoo-dist 275 | /efi 276 | /efi/EFI 277 | 278 | 4 directories, 4 files" 279 | TEST_CASES["generic-uki -dracut -systemd -systemd-boot uki -ukify -grub -refind"]=\ 280 | "/boot 281 | /efi 282 | /efi/EFI 283 | /efi/EFI/Linux 284 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 285 | 286 | 3 directories, 1 file" 287 | TEST_CASES["generic-uki -dracut -systemd -systemd-boot uki -ukify grub -refind"]=\ 288 | "/boot 289 | /boot/grub 290 | /efi 291 | /efi/EFI 292 | /efi/EFI/Linux 293 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 294 | 295 | 5 directories, 1 file" 296 | TEST_CASES["generic-uki -dracut systemd -systemd-boot -uki -ukify -grub -refind"]=\ 297 | "/boot 298 | /boot/initramfs-${INST_KV}-gentoo-dist.img 299 | /boot/kernel-${INST_KV}-gentoo-dist 300 | /efi 301 | /efi/EFI 302 | 303 | 3 directories, 2 files" 304 | TEST_CASES["generic-uki -dracut systemd -systemd-boot -uki -ukify grub -refind"]=\ 305 | "/boot 306 | /boot/grub 307 | /boot/initramfs-${INST_KV}-gentoo-dist.img 308 | /boot/kernel-${INST_KV}-gentoo-dist 309 | /efi 310 | /efi/EFI 311 | 312 | 4 directories, 2 files" 313 | TEST_CASES["generic-uki -dracut systemd -systemd-boot uki -ukify -grub -refind"]=\ 314 | "/boot 315 | /efi 316 | /efi/EFI 317 | /efi/EFI/Linux 318 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 319 | 320 | 3 directories, 1 file" 321 | TEST_CASES["generic-uki -dracut systemd -systemd-boot uki -ukify grub -refind"]=\ 322 | "/boot 323 | /boot/grub 324 | /efi 325 | /efi/EFI 326 | /efi/EFI/Linux 327 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 328 | 329 | 5 directories, 1 file" 330 | TEST_CASES["generic-uki -dracut systemd systemd-boot -uki -ukify -grub -refind"]=\ 331 | "/boot 332 | /efi 333 | /efi/EFI 334 | /efi/gentoo 335 | /efi/gentoo/${INST_KV}-gentoo-dist 336 | /efi/gentoo/${INST_KV}-gentoo-dist/initrd 337 | /efi/gentoo/${INST_KV}-gentoo-dist/linux 338 | /efi/loader 339 | /efi/loader/entries 340 | /efi/loader/entries/gentoo-${INST_KV}-gentoo-dist.conf 341 | 342 | 6 directories, 3 files" 343 | TEST_CASES["generic-uki -dracut systemd systemd-boot uki -ukify -grub -refind"]=\ 344 | "/boot 345 | /efi 346 | /efi/EFI 347 | /efi/EFI/Linux 348 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 349 | 350 | 3 directories, 1 file" 351 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot -uki -ukify -grub refind"]=\ 352 | "/boot 353 | /boot/System.map-${INST_KV}-gentoo-dist 354 | /boot/config-${INST_KV}-gentoo-dist 355 | /boot/vmlinuz-${INST_KV}-gentoo-dist 356 | /boot/vmlinuz-${INST_KV}-gentoo-dist.png 357 | /efi 358 | /efi/EFI 359 | 360 | 3 directories, 4 files" 361 | TEST_CASES["-generic-uki -dracut -systemd -systemd-boot uki ukify -grub refind"]=\ 362 | "/boot 363 | /efi 364 | /efi/EFI 365 | /efi/EFI/Linux 366 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 367 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.png 368 | 369 | 3 directories, 2 files" 370 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot -uki -ukify -grub refind"]=\ 371 | "/boot 372 | /boot/kernel-${INST_KV}-gentoo-dist 373 | /boot/kernel-${INST_KV}-gentoo-dist.png 374 | /efi 375 | /efi/EFI 376 | 377 | 3 directories, 2 files" 378 | TEST_CASES["generic-uki -dracut systemd -systemd-boot -uki -ukify -grub refind"]=\ 379 | "/boot 380 | /boot/initramfs-${INST_KV}-gentoo-dist.img 381 | /boot/kernel-${INST_KV}-gentoo-dist 382 | /boot/kernel-${INST_KV}-gentoo-dist.png 383 | /efi 384 | /efi/EFI 385 | 386 | 3 directories, 3 files" 387 | TEST_CASES["-generic-uki -dracut systemd -systemd-boot uki ukify -grub refind"]=\ 388 | "/boot 389 | /efi 390 | /efi/EFI 391 | /efi/EFI/Linux 392 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.efi 393 | /efi/EFI/Linux/gentoo-${INST_KV}-gentoo-dist.png 394 | 395 | 3 directories, 2 files" 396 | 397 | FAILURES=() 398 | 399 | for case in "${!TEST_CASES[@]}"; do 400 | rm -rf /boot/* /efi/* || { echo "Error at case USE=\"${case}\"" && exit 1; } 401 | mkdir -p /efi/EFI || { echo "Error at case USE=\"${case}\"" && exit 1; } 402 | echo "Testing case USE=\"${case}\" ..." 403 | 404 | emerge --rage-clean --quiet --quiet-unmerge-warn sys-kernel/gentoo-kernel-bin || { echo "Error at case USE=\"${case}\"" && exit 1; } 405 | USE="${case}" emerge --quiet '=sys-kernel/installkernel-9999' || { echo "Error at case USE=\"${case}\"" && exit 1; } 406 | INSTALLKERNEL_VERBOSE=1 USE="${case}" emerge --quiet sys-kernel/gentoo-kernel-bin || { echo "Error at case USE=\"${case}\"" ; cat "/var/tmp/portage/sys-kernel/gentoo-kernel-bin-${INST_KV}/temp/build.log" ; exit 1; } 407 | tree="$(tree -ifnav /boot /efi)" 408 | if [[ "${TEST_CASES[${case}]}" == "${tree}" ]]; then 409 | echo "Case USE=\"${case}\" matches" 410 | else 411 | echo "Case USE=\"${case}\" does not match!" 412 | 413 | FAILURES+=(" 414 | Case USE=\"${case}\" failed: 415 | Expected: 416 | ${TEST_CASES[${case}]} 417 | 418 | Actual: 419 | ${tree} 420 | ") 421 | fi 422 | done 423 | 424 | echo "" 425 | 426 | # Cleanup fake ESP 427 | rm -rf /boot/* /efi/* || exit 1 428 | umount /efi || exit 1 429 | losetup -d "${FAKE_EFI}" || exit 1 430 | 431 | if [[ ${#FAILURES[@]} -eq 0 ]]; then 432 | echo "All tests succeeded" 433 | exit 0 434 | else 435 | echo "The following ${#FAILURES[@]} tests failed" 436 | (IFS=$'\n'; echo "${FAILURES[*]}") 437 | exit 1 438 | fi 439 | -------------------------------------------------------------------------------- /run_tests_in_docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | IMAGE="installkernel-testing" 6 | 7 | docker build -t ${IMAGE} . 8 | docker run --privileged=true --mount type=bind,source="$(pwd)",target=/tmp/installkernel-gentoo-9999,readonly -t ${IMAGE} 9 | --------------------------------------------------------------------------------