[arch-projects] [mkinitcpio] [PATCH] Add 'microcode' hooks
Weng Xuetian
wengxt at gmail.com
Sun Nov 2 07:18:00 UTC 2014
Add early microcode support with early cpio. All files added under
/early_root will be created as a separate cpio prepend to original one.
Add a early_cpio file to early cpio to detect whether cpio contains
early cpio, thus we can have lsinitcpio work normally like old one.
---
.gitignore | 1 +
Makefile | 9 +++-
install/microcode | 24 +++++++++++
lsinitcpio | 35 +++++++++++++---
mkinitcpio | 13 +++++-
skipcpio.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 198 insertions(+), 7 deletions(-)
create mode 100644 install/microcode
create mode 100644 skipcpio.c
diff --git a/.gitignore b/.gitignore
index a814a0f..1e501f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ lsinitcpio.1
*~
*.bak
mkinitcpio-*.tar.gz
+skipcpio
diff --git a/Makefile b/Makefile
index 5af0eb2..a3a3591 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,10 @@ DIRS = \
/usr/lib/systemd/system/shutdown.target.wants \
/usr/lib/tmpfiles.d
-all: doc
+all: doc skipcpio
+
+skipcpio: skipcpio.c
+ $(CC) skipcpio.c -o skipcpio
MANPAGES = \
man/mkinitcpio.8 \
@@ -40,6 +43,7 @@ install: all
< mkinitcpio > $(DESTDIR)/usr/bin/mkinitcpio
sed -e 's|\(^_f_functions\)=.*|\1=/usr/lib/initcpio/functions|' \
+ -e 's|\(^_f_skipcpio\)=.*|\1=/usr/lib/initcpio/skipcpio|' \
-e 's|%VERSION%|$(VERSION)|g' \
< lsinitcpio > $(DESTDIR)/usr/bin/lsinitcpio
@@ -67,6 +71,8 @@ install: all
ln -s mkinitcpio $(DESTDIR)/usr/share/bash-completion/completions/lsinitcpio
install -m644 shell/zsh-completion $(DESTDIR)/usr/share/zsh/site-functions/_mkinitcpio
+ install -m755 skipcpio $(DESTDIR)/usr/lib/initcpio/skipcpio
+
doc: $(MANPAGES)
man/%: man/%.txt Makefile
a2x -d manpage \
@@ -76,6 +82,7 @@ man/%: man/%.txt Makefile
clean:
$(RM) mkinitcpio-${VERSION}.tar.gz $(MANPAGES)
+ $(RM) skipcpio
dist: doc
echo $(VERSION) > VERSION
diff --git a/install/microcode b/install/microcode
new file mode 100644
index 0000000..4dfd69e
--- /dev/null
+++ b/install/microcode
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+build() {
+ ucode_dir=(amd-ucode intel-ucode)
+ ucode_dest=(AuthenticAMD.bin GenuineIntel.bin)
+
+ for idx in 0 1; do
+ fw=${ucode_dir[$idx]}
+ for fwpath in "${_d_firmware[@]}"; do
+ if [[ -d $fwpath/$fw ]]; then
+ add_dir '/early_root/kernel/x86/microcode'
+ cat $fwpath/$fw/* > $BUILDROOT/early_root/kernel/x86/microcode/${ucode_dest[$idx]}
+ fi
+ done
+ done
+}
+
+help() {
+ cat <<HELPEOF
+This hook generate early ucode update
+HELPEOF
+}
+
+# vim: set ft=sh ts=4 sw=4 et:
diff --git a/lsinitcpio b/lsinitcpio
index 9567b79..902bfe2 100755
--- a/lsinitcpio
+++ b/lsinitcpio
@@ -6,8 +6,10 @@
shopt -s extglob
_list='--list'
-_optcolor=1 _optverbose=
+_optcolor=1 _optverbose= _optnoearly=1
_f_functions=functions
+_f_skipcpio=./skipcpio
+_tmp_files=()
usage() {
cat<<USAGE
@@ -21,6 +23,7 @@ usage: ${0##*/} [action] [options] <initramfs>
-x, --extract extract image to disk
Options:
+ -e, --early display early cpio if possible
-h, --help display this help
-n, --nocolor disable colorized output
-V, --version display version information
@@ -131,7 +134,8 @@ analyze_image() {
local kernver ratio columns=$(tput cols) image=$1
workdir=$(mktemp -d --tmpdir lsinitcpio.XXXXXX)
- trap 'rm -rf "$workdir"' EXIT
+ _tmp_files+=("$workdir")
+ trap 'rm -rf "${_tmp_files[@]}"' EXIT
# fallback in case tput failed us
columns=${columns:-80}
@@ -174,7 +178,7 @@ analyze_image() {
explicitmod=($MODULES)
# print results
- imagename=$_image
+ imagename=$_origimage
[[ -L $_image ]] && imagename+=" -> $(readlink -e "$_image")"
msg 'Image: %s %s' "$imagename"
[[ $version ]] && msg 'Created with mkinitcpio %s' "$version"
@@ -225,10 +229,18 @@ analyze_image() {
printf ' %s\n' $CLEANUPHOOKS
printf '\n'
fi
+
+ msg 'Contains early CPIO:'
+ if (( _hasearly )); then
+ printf ' yes\n'
+ else
+ printf ' no\n'
+ fi
+ printf '\n'
}
-_opt_short='achlnVvx'
-_opt_long=('analyze' 'config' 'help' 'list' 'nocolor' 'version' 'verbose' 'extract')
+_opt_short='achlenVvx'
+_opt_long=('analyze' 'config' 'help' 'list' 'early' 'nocolor' 'version' 'verbose' 'extract')
parseopts "$_opt_short" "${_opt_long[@]}" -- "$@" || exit
set -- "${OPTRET[@]}"
@@ -245,6 +257,8 @@ while :; do
exit 0 ;;
-l|--list)
_optlistcontents=1 ;;
+ -e|--early)
+ _optnoearly=0 ;;
-n|--nocolor)
_optcolor=0 ;;
-V|--version)
@@ -262,6 +276,8 @@ while :; do
done
_image=$1
+_origimage=$1
+_hasearly=0
if [[ -t 1 ]] && (( _optcolor )); then
try_enable_color
@@ -281,6 +297,15 @@ esac
# read compression type
_compress=$(detect_filetype "$_image") || exit
+if (( _optnoearly )) && decomp "$_image" | bsdcpio -i --quiet --list | grep -q '^early_cpio'; then
+ _hasearly=1
+ _tmp_image=$(mktemp --tmpdir lsinitcpio.XXXXXX)
+ _tmp_files+=("$_tmp_image")
+ trap 'rm -rf "${_tmp_files[@]}"' EXIT
+ $_f_skipcpio $_image > $_tmp_image
+ _image=$_tmp_image
+fi
+
if (( _optanalyze )); then
analyze_image "$_image"
elif (( _optshowconfig )); then
diff --git a/mkinitcpio b/mkinitcpio
index 01fe8ba..cfe5747 100755
--- a/mkinitcpio
+++ b/mkinitcpio
@@ -221,10 +221,21 @@ build_image() {
cpio_opts+=('-R' '0:0')
fi
+ echo -n > "$out"
+ if [[ -d "$BUILDROOT/early_root" ]]; then
+ pushd "$BUILDROOT/early_root" >/dev/null
+ touch "$BUILDROOT/early_root/early_cpio"
+ find . -mindepth 1 -printf "%P\0" |
+ LANG=C bsdcpio "${cpio_opts[@]}" >> "$out"
+ popd >/dev/null
+
+ rm -rf "$BUILDROOT/early_root"
+ fi
+
pushd "$BUILDROOT" >/dev/null
find . -print0 |
LANG=C bsdcpio "${cpio_opts[@]}" |
- $compress $COMPRESSION_OPTIONS > "$out"
+ $compress $COMPRESSION_OPTIONS >> "$out"
pipesave=("${PIPESTATUS[@]}") # save immediately
popd >/dev/null
diff --git a/skipcpio.c b/skipcpio.c
new file mode 100644
index 0000000..445d7f6
--- /dev/null
+++ b/skipcpio.c
@@ -0,0 +1,123 @@
+/* dracut-install.c -- install files and executables
+
+ Copyright (C) 2012 Harald Hoyer
+ Copyright (C) 2012 Red Hat, Inc. All rights reserved.
+
+ This program is free software: you can redistribute it and/or modify
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define PROGRAM_VERSION_STRING "1"
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define CPIO_END "TRAILER!!!"
+#define CPIO_ENDLEN (sizeof(CPIO_END)-1)
+
+static char buf[CPIO_ENDLEN * 2 + 1];
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ size_t s;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <file>\n", argv[0]);
+ exit(1);
+ }
+
+ f = fopen(argv[1], "r");
+
+ if (f == NULL) {
+ fprintf(stderr, "Cannot open file '%s'\n", argv[1]);
+ exit(1);
+ }
+
+ s = fread(buf, 6, 1, f);
+ if (s <= 0) {
+ fprintf(stderr, "Read error from file '%s'\n", argv[1]);
+ fclose(f);
+ exit(1);
+ }
+ fseek(f, 0, SEEK_SET);
+
+ /* check, if this is a cpio archive */
+ if ((buf[0] == 0x71 && buf[1] == 0xc7)
+ || (buf[0] == '0' && buf[1] == '7' && buf[2] == '0' && buf[3] == '7' && buf[4] == '0' && buf[5] == '1')) {
+ long pos = 0;
+
+ /* Search for CPIO_END */
+ do {
+ char *h;
+ fseek(f, pos, SEEK_SET);
+ buf[sizeof(buf) - 1] = 0;
+ s = fread(buf, CPIO_ENDLEN, 2, f);
+ if (s <= 0)
+ break;
+
+ h = strstr(buf, CPIO_END);
+ if (h) {
+ pos = (h - buf) + pos + CPIO_ENDLEN;
+ fseek(f, pos, SEEK_SET);
+ break;
+ }
+ pos += CPIO_ENDLEN;
+ } while (!feof(f));
+
+ if (feof(f)) {
+ /* CPIO_END not found, just cat the whole file */
+ fseek(f, 0, SEEK_SET);
+ } else {
+ /* skip zeros */
+ while (!feof(f)) {
+ size_t i;
+
+ buf[sizeof(buf) - 1] = 0;
+ s = fread(buf, 1, sizeof(buf) - 1, f);
+ if (s <= 0)
+ break;
+
+ for (i = 0; (i < s) && (buf[i] == 0); i++) ;
+
+ if (buf[i] != 0) {
+ pos += i;
+ fseek(f, pos, SEEK_SET);
+ break;
+ }
+
+ pos += s;
+ }
+ }
+ }
+ /* cat out the rest */
+ while (!feof(f)) {
+ s = fread(buf, 1, sizeof(buf), f);
+ if (s <= 0)
+ break;
+
+ s = fwrite(buf, 1, s, stdout);
+ if (s <= 0)
+ break;
+ }
+ fclose(f);
+
+ return EXIT_SUCCESS;
+}
--
2.0.2
More information about the arch-projects
mailing list