mirror of
git://git.yoctoproject.org/meta-intel.git
synced 2025-07-19 12:59:03 +02:00
rmc: remove
It's not being maintained anymore and the scripts have not been kept in sync with upstream for quite some time. Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
This commit is contained in:
parent
7c469177e8
commit
c12c166592
4
README
4
README
|
@ -239,10 +239,6 @@ Other software
|
||||||
the Intel power clamp driver.
|
the Intel power clamp driver.
|
||||||
(https://01.org/linux-thermal-daemon/documentation/introduction-thermal-daemon)
|
(https://01.org/linux-thermal-daemon/documentation/introduction-thermal-daemon)
|
||||||
|
|
||||||
* RMC - Runtime Machine Configuration, which allows the bootload to determine
|
|
||||||
board and CPU information in order to set specific kernel command line
|
|
||||||
information at startup.
|
|
||||||
|
|
||||||
The intel-common kernel package architecture
|
The intel-common kernel package architecture
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
# rmc-boot bbclass
|
|
||||||
# Deploy central RMC database file to ESP
|
|
||||||
|
|
||||||
IMAGE_INSTALL_append = " rmc"
|
|
||||||
RMC_BOOTLOADER ?= "systemd-boot"
|
|
||||||
|
|
||||||
inherit ${RMC_BOOTLOADER}
|
|
||||||
|
|
||||||
do_bootimg[depends] += "${MLPREFIX}rmc-db:do_deploy"
|
|
||||||
|
|
||||||
efi_populate_append() {
|
|
||||||
if [ -f ${DEPLOY_DIR_IMAGE}/rmc.db ]; then
|
|
||||||
install -m 0400 ${DEPLOY_DIR_IMAGE}/rmc.db ${DEST}/rmc.db
|
|
||||||
else
|
|
||||||
rm -f ${DEST}/rmc.db
|
|
||||||
fi
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
# RMC database bbclass
|
|
||||||
# provide functions to generate RMC database file on build host (native)
|
|
||||||
|
|
||||||
DEPENDS += "rmc-native"
|
|
||||||
|
|
||||||
# rmc_generate_db()
|
|
||||||
# $1: a list of directories. Each directory holds directories for a group of
|
|
||||||
# boards.
|
|
||||||
# $2: path_name of rmc generates database file and records
|
|
||||||
#
|
|
||||||
# WARNING: content of directory of database file will be removed.
|
|
||||||
#
|
|
||||||
# Each board directory shall contain a fingerprint file (*.fp) at least, with
|
|
||||||
# optional file blob(s) associated to the type of board. If a board directory
|
|
||||||
# has no file blob, no record is created for that board.
|
|
||||||
#
|
|
||||||
# An example of two directories each of which contains two boards for RMC:
|
|
||||||
# (All file and directory names are for illustration purpose.)
|
|
||||||
#
|
|
||||||
# dir_1/
|
|
||||||
# board_1/
|
|
||||||
# board_1_fingerprint.fp
|
|
||||||
# file_1.blob
|
|
||||||
# board_2/
|
|
||||||
# board_2.fp
|
|
||||||
# dir_2/
|
|
||||||
# board_3/
|
|
||||||
# b3.fp
|
|
||||||
# file_1.blob
|
|
||||||
# file_2.conf
|
|
||||||
# board_4/
|
|
||||||
# board_foo.fp
|
|
||||||
# mylib.config
|
|
||||||
#
|
|
||||||
# To generate a RMC database "rmc.db" with data of all (actually 3) of boards in
|
|
||||||
# a directory "deploy_dir":
|
|
||||||
#
|
|
||||||
# rmc_generate_db "dir_1 dir_2" "deploy_dir/rmc.db"
|
|
||||||
#
|
|
||||||
# The board_2 will be skipped. No record or any data for it is packed in
|
|
||||||
# generated database because it only contains a fingerprint file.
|
|
||||||
#
|
|
||||||
|
|
||||||
rmc_generate_db () {
|
|
||||||
RMC_BOARD_DIRS=$1
|
|
||||||
|
|
||||||
if [ "$#" -ne 2 ]; then
|
|
||||||
echo "rmc_generate_db(): Wrong number of arguments: $#"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
RMC_DB_DIR=$(dirname "$2")
|
|
||||||
RMC_RECORDS=""
|
|
||||||
|
|
||||||
rm -rf ${RMC_DB_DIR}
|
|
||||||
mkdir -p ${RMC_DB_DIR}
|
|
||||||
|
|
||||||
# generate rmc database
|
|
||||||
for topdir in ${RMC_BOARD_DIRS}; do
|
|
||||||
# For all board dirs in a topdir:
|
|
||||||
CUR_BOARD_DIRS=$(find ${topdir}/* -type d)
|
|
||||||
for board_dir in ${CUR_BOARD_DIRS}; do
|
|
||||||
CUR_FINGERPRINT=$(find ${board_dir}/ -name "*.fp")
|
|
||||||
|
|
||||||
# disallow a board directory without any fingerprint file in it.
|
|
||||||
if [ -z "${CUR_FINGERPRINT}" ]; then
|
|
||||||
echo "Cannot find RMC fingerprint file in ${board_dir}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
CUR_FILES=$(find ${board_dir}/ -type f |grep -v '\.fp$' || true)
|
|
||||||
|
|
||||||
# allow a directory only with fingerprint file. Developer may
|
|
||||||
# check in fingerprint for future use.
|
|
||||||
if [ -z "${CUR_FILES}" ]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
for fp in ${CUR_FINGERPRINT}; do
|
|
||||||
fullname=$(basename ${fp})
|
|
||||||
CUR_TAG="${fullname%.*}"
|
|
||||||
CUR_RECORD=${RMC_DB_DIR}/${CUR_TAG}.rec
|
|
||||||
rmc -R -f ${fp} -b ${CUR_FILES} -o ${CUR_RECORD}
|
|
||||||
RMC_RECORDS="${RMC_RECORDS} ${CUR_RECORD}"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ ! -z "${RMC_RECORDS}" ]; then
|
|
||||||
rmc -D ${RMC_RECORDS} -o "$2"
|
|
||||||
fi
|
|
||||||
}
|
|
|
@ -14,8 +14,6 @@ RECIPE_MAINTAINER_pn-linux-intel = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-linux-intel-rt = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-linux-intel-rt = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-lms7 = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-lms7 = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-lms8 = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-lms8 = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-rmc = "Anuj Mittal <anuj.mittal@intel.com>"
|
|
||||||
RECIPE_MAINTAINER_pn-rmc-db = "Anuj Mittal <anuj.mittal@intel.com>"
|
|
||||||
RECIPE_MAINTAINER_pn-thermald = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-thermald = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-va-intel = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-va-intel = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
RECIPE_MAINTAINER_pn-xf86-video-ast = "Anuj Mittal <anuj.mittal@intel.com>"
|
RECIPE_MAINTAINER_pn-xf86-video-ast = "Anuj Mittal <anuj.mittal@intel.com>"
|
||||||
|
|
|
@ -34,5 +34,5 @@ SERIAL_CONSOLES = "115200;ttyS0 115200;ttyS1 115200;ttyPCH0"
|
||||||
APPEND += "rootwait console=ttyS0,115200 console=ttyPCH0,115200 console=tty0"
|
APPEND += "rootwait console=ttyS0,115200 console=ttyPCH0,115200 console=tty0"
|
||||||
|
|
||||||
IMAGE_FSTYPES += "wic"
|
IMAGE_FSTYPES += "wic"
|
||||||
WKS_FILE ?= "${@bb.utils.contains_any("EFI_PROVIDER", "systemd-boot rmc-boot", "systemd-bootdisk-microcode.wks", "grub-bootdisk-microcode.wks", d)}"
|
WKS_FILE ?= "${@bb.utils.contains_any("EFI_PROVIDER", "systemd-boot", "systemd-bootdisk-microcode.wks", "grub-bootdisk-microcode.wks", d)}"
|
||||||
WKS_FILE_DEPENDS_append = " intel-microcode"
|
WKS_FILE_DEPENDS_append = " intel-microcode"
|
||||||
|
|
|
@ -41,5 +41,5 @@ SERIAL_CONSOLES = "115200;ttyS0 115200;ttyS1 115200;ttyS2"
|
||||||
APPEND += "rootwait console=ttyS0,115200 console=tty0"
|
APPEND += "rootwait console=ttyS0,115200 console=tty0"
|
||||||
|
|
||||||
IMAGE_FSTYPES += "wic"
|
IMAGE_FSTYPES += "wic"
|
||||||
WKS_FILE ?= "${@bb.utils.contains_any("EFI_PROVIDER", "systemd-boot rmc-boot", "systemd-bootdisk-microcode.wks", "grub-bootdisk-microcode.wks", d)}"
|
WKS_FILE ?= "${@bb.utils.contains_any("EFI_PROVIDER", "systemd-boot", "systemd-bootdisk-microcode.wks", "grub-bootdisk-microcode.wks", d)}"
|
||||||
WKS_FILE_DEPENDS_append = " intel-microcode"
|
WKS_FILE_DEPENDS_append = " intel-microcode"
|
||||||
|
|
|
@ -1,373 +0,0 @@
|
||||||
Runtime Machine Configuration (RMC)
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
Table of Contents
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
Usage
|
|
||||||
Enable RMC Feature
|
|
||||||
Examples
|
|
||||||
Troubleshooting
|
|
||||||
When you (don't) need RMC feature
|
|
||||||
|
|
||||||
|
|
||||||
Introduction:
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
RMC Project - a light-weight project provide developers a mechanism to keep
|
|
||||||
their software implementation board-type agnostic, yet still able to customize
|
|
||||||
software behavior according to the type of a running board at runtime. Recipes
|
|
||||||
and bbclasses are available for other components to reuse to construct their own
|
|
||||||
RMC database.
|
|
||||||
|
|
||||||
RMC Feature - An end-to-end solution based on RMC project to have a generic
|
|
||||||
image capable to apply board-type-specific quirks and configurations for a board
|
|
||||||
at runtime. It consists of a modified bootloader (systemd-boot), an updated EFI
|
|
||||||
installer, recipes, bbclass and RMC project.
|
|
||||||
|
|
||||||
RMC feature supports special customizations cannot be covered by conventional
|
|
||||||
auto-detection features based on probing a hardware module because they happen
|
|
||||||
at a board or a product level. For example:
|
|
||||||
- tty console for kernel log output in kernel cmdline
|
|
||||||
- default audio route configuration
|
|
||||||
- network configuration
|
|
||||||
- UI layout
|
|
||||||
- requirement to software driven by a mechanical design
|
|
||||||
- or static configuration bits for a physical bus that doesn't support to
|
|
||||||
identify devices or their presence at runtime
|
|
||||||
|
|
||||||
An image with the feature has ability to configure supported boards with data
|
|
||||||
associated only to a type of board to get full functionality of the target at
|
|
||||||
runtime, yet still with a single image.
|
|
||||||
|
|
||||||
Effect after installation is identical to what a conventional image specially
|
|
||||||
customized for a type of board (depending on the way to deploy image).
|
|
||||||
|
|
||||||
Main functions of RMC Feature:
|
|
||||||
|
|
||||||
Show board-specific boot entries in boot menu and boot system with configuration
|
|
||||||
(boot title, boot options, etc) in a selected boot entry.
|
|
||||||
|
|
||||||
Support a "global" kernel boot command line fragment which is effective for all
|
|
||||||
boot entries.
|
|
||||||
|
|
||||||
Deploy file blobs and create directories specific to the type of running board.
|
|
||||||
|
|
||||||
Beside from this document, you can also find several built-in examples in
|
|
||||||
common/recipes-bsp/rmc/boards/. Refer to "Examples" section.
|
|
||||||
|
|
||||||
You can also add new board types in your layer via a simple variable.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Usage
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
Developers are suggested to organize all board-specific files in their own layer
|
|
||||||
following this example, so that RMC recipes can pick up them correctly in build.
|
|
||||||
|
|
||||||
- my_top_dir/ Top directory of your board (Note 0)
|
|
||||||
|- rmc-db.bbappend bbappend file to rmc-db recipe at a lower level
|
|
||||||
|- rmc/
|
|
||||||
|- target_board_1/ subdirectory of a board.
|
|
||||||
| |- board1.fp fingerprint file must be provided (NOTE 1)
|
|
||||||
| |- BOOTENTRY.CONFIG optional config file for boot entries. (NOTE 2)
|
|
||||||
| |- INSTALLER.CONFIG optional config file for installer. (NOTE 3)
|
|
||||||
| |- POSTINSTALL.sh optional script hook for installer (NOTE 4)
|
|
||||||
| |- board_file_1 A file blob specific to the type of board
|
|
||||||
| |- board_file_2 An another file specific to the type of board
|
|
||||||
| |- ...more files
|
|
||||||
|- target_board_2/ subdirectory of another board.
|
|
||||||
|- board_2_v2.fp fingerprint file for board 2.
|
|
||||||
|- BOOTENTRY.CONFIG
|
|
||||||
|- INSTALLER.CONFIG
|
|
||||||
|- board_file_1
|
|
||||||
|- ...more files
|
|
||||||
|
|
||||||
Note 0:
|
|
||||||
Developers are expected to use variable RMC_BOARD_DATA_DIRS to specify data of
|
|
||||||
boards packed into RMC database file generated in a build. The default value of
|
|
||||||
the variable in meta-intel specifies a group of boards. They work as examples
|
|
||||||
and necessary quirks for these boards to function properly. Developers can
|
|
||||||
override, append to the default boards with data of their own boards in the
|
|
||||||
database file, or even disable the generation of the database file.
|
|
||||||
|
|
||||||
For example, in your local.conf file:
|
|
||||||
|
|
||||||
This line adds your boards along with the default boards into RMC database file,
|
|
||||||
assuming you have a directory named "rmc" which has a subdirectory for each
|
|
||||||
board:
|
|
||||||
|
|
||||||
RMC_BOARD_DATA_DIRS_append = " /path_of/rmc"
|
|
||||||
|
|
||||||
This line directs RMC to pack data of your boards only, without data of the
|
|
||||||
default boards in meta-intel:
|
|
||||||
|
|
||||||
RMC_BOARD_DATA_DIRS = "/path_of/rmc"
|
|
||||||
|
|
||||||
And this line disables database generation:
|
|
||||||
|
|
||||||
RMC_BOARD_DATA_DIRS = ""
|
|
||||||
|
|
||||||
Please also refer to the "Example 1" in this document.
|
|
||||||
|
|
||||||
Subdirectory is not supported in a board's directory.
|
|
||||||
|
|
||||||
Note 1:
|
|
||||||
Fingerprint files must be provided and with ".fp" at the end of their names.
|
|
||||||
Fingerprint can be obtained by running RMC tool on your board. An easy way is to
|
|
||||||
live-boot USB stick flashed with any image enabled this feature on your board,
|
|
||||||
then run this command:
|
|
||||||
|
|
||||||
# rmc -F -o my_board.fp
|
|
||||||
|
|
||||||
Or you will need to build RMC tool for the architecture of your board, 32 or
|
|
||||||
64 bit x86, from RMC project.
|
|
||||||
|
|
||||||
You can run RMC tool without any argument to get usage and examples.
|
|
||||||
|
|
||||||
DO NOT NAME ANY FILE ENDING WITH '.fp' IF IT IS NOT A RMC FINGERPRINT FILE.
|
|
||||||
|
|
||||||
If you do need a .fp file deployed onto target, please rename it in source and
|
|
||||||
specify the real name of file on target in INSTALLER.CONFIG.
|
|
||||||
|
|
||||||
Note 2:
|
|
||||||
At runtime, RMC bootloader tries to fetch this file specific to the board at run
|
|
||||||
time, then tries to fetch each boot entry file specified in BOOTENTRY.CONFIG and
|
|
||||||
show them in boot menu options. The format of this file is very simple. Each
|
|
||||||
line is the name of a boot entry file:
|
|
||||||
|
|
||||||
boot.conf
|
|
||||||
Install.conf
|
|
||||||
myrmcboot.conf
|
|
||||||
|
|
||||||
Name of a boot entry file is defined by developer so it can be anything. But the
|
|
||||||
name of config file is what RMC bootloader looks up in RMC database, so it must
|
|
||||||
be named BOOTENTRY.CONFIG.
|
|
||||||
|
|
||||||
Bootloader skips loading entry conf files from disk once any entry is loaded
|
|
||||||
from RMC database.
|
|
||||||
|
|
||||||
Note 3:
|
|
||||||
At runtime, RMC installer tries to fetch INSTALLER.CONFIG file specific to the
|
|
||||||
board, then tries to fetch each file specified in this config file, and then
|
|
||||||
deploy the file onto target with its permissions, UID, GID and other attributes
|
|
||||||
also specified in this config file if file for the board can be retrieved from
|
|
||||||
RMC database. The format of this file is (# is for comment line)
|
|
||||||
|
|
||||||
# name:uid:gid:mode:path_on_target
|
|
||||||
# to create a directory, add a “/” at the end of path_on_target:
|
|
||||||
audio_policy:0:0:600:/etc/audio/
|
|
||||||
audio_def_policy:0:0:600:/etc/audio/audio_policy
|
|
||||||
|
|
||||||
The above example creates /etc/audio directory first, then fetch a file named
|
|
||||||
“audio_def_policy” from RMC database for the board, then copy it to /etc/audio/
|
|
||||||
with a new name “audio_policy”.
|
|
||||||
|
|
||||||
If this config file is not provided, No data in RMC database is deployed to the
|
|
||||||
target.
|
|
||||||
|
|
||||||
Some steps defined by developers could not be supported on a filesystem.
|
|
||||||
Installer simply ignores any errors in RMC deployment stage.
|
|
||||||
|
|
||||||
The name of this config file is what installer looks up first, so it must be
|
|
||||||
INSTALLER.CONFIG.
|
|
||||||
|
|
||||||
Note 4:
|
|
||||||
At the end of RMC deployment during installation, RMC installer queries a script
|
|
||||||
file POSTINSTALL.sh from RMC database file, and execute it when query is
|
|
||||||
successful on the running board. This hook provides developers almost ultimate
|
|
||||||
flexibility to retouch what have been deployed on the target. There are some
|
|
||||||
steps still can override results from this hook for boot entries and KBOOTPARAM.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Enable RMC Feature
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
To enable the RMC feature please add the following variables to your local.conf.
|
|
||||||
|
|
||||||
DISTRO_FEATURES_append = " rmc"
|
|
||||||
EFI_PROVIDER = "rmc-boot"
|
|
||||||
|
|
||||||
The default EFI bootloader used with RMC is systemd-boot. To change the default
|
|
||||||
bootloader please overwrite the RMC_BOOTLOADER variable in your local.conf
|
|
||||||
|
|
||||||
Note:
|
|
||||||
Image could be still bootable if you only have either of two lines, but RMC
|
|
||||||
feature could not be fully functional, depending on the availability of the
|
|
||||||
database file, installer and the rmc tool.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
We checked in configuration data in common/recipes-bsp/rmc/boards/ for several
|
|
||||||
boards, to help users to understand the RMC feature. These examples are also for
|
|
||||||
validation. For any example you find not working as what this section depicts,
|
|
||||||
it should be treated as a bug to be fixed.
|
|
||||||
|
|
||||||
To test this feature with examples, enable it and build an image first, then
|
|
||||||
boot the built image on supported boards. Examples are always built in when the
|
|
||||||
feature is enabled, except for the EXAMPLE 1.
|
|
||||||
|
|
||||||
EXAMPLE 1: Support a new board type:
|
|
||||||
(1) enable the feature and do a build to get a live-boot image by adding these
|
|
||||||
lines in conf/local.conf:
|
|
||||||
DISTRO_FEATURES_append = " rmc"
|
|
||||||
EFI_PROVIDER = "rmc-boot"
|
|
||||||
|
|
||||||
(2) flash the image to a USB stick and boot it on your board
|
|
||||||
|
|
||||||
(3) in super user mode, run "rmc -F -o my_board.fp"
|
|
||||||
|
|
||||||
(4) create directories in your host "mkdir -p my_top_dir/my_rmc/my_board"
|
|
||||||
|
|
||||||
(5) copy my_board.fp from target to my_top_dir/my_rmc/my_board/ on host
|
|
||||||
|
|
||||||
(6) create a file my_top_dir/my_rmc/my_board/KBOOTPARAM, put some fake
|
|
||||||
and harmless options in a single line, say, "loglevel=7"
|
|
||||||
|
|
||||||
(7) create a file my_top_dir/rmc-db.bbappend, put this single line in it:
|
|
||||||
RMC_BOARD_DATA_DIRS_append := " ${THISDIR}/my_rmc"
|
|
||||||
From parent directory of my_top_dir, the tree should look like:
|
|
||||||
my_top_dir/
|
|
||||||
my_rmc/
|
|
||||||
my_board/
|
|
||||||
KBOOTPARAM
|
|
||||||
my_board.fp
|
|
||||||
rmc-db.bbappend
|
|
||||||
Later, you can add more board directories in my_rmc directory.
|
|
||||||
|
|
||||||
(8) modify build configuration to add my_top_dir into build, for example, put
|
|
||||||
this line in a bblayers.conf:
|
|
||||||
BBFILES += "/full/path/of/my_top_dir/rmc-db.bbappend"
|
|
||||||
|
|
||||||
(9) build image again then boot it on your board
|
|
||||||
|
|
||||||
(10) Once you login to shell, new options should be effective, run this command
|
|
||||||
"cat /proc/cmdline" to verify the result.
|
|
||||||
|
|
||||||
EXAMPLE 2: Board-specific boot entry
|
|
||||||
MinnowBoard MAX and B3 version:
|
|
||||||
common/recipes-bsp/rmc/boards/minnowmax
|
|
||||||
common/recipes-bsp/rmc/boards/minnowmaxB3
|
|
||||||
|
|
||||||
We have found two identities (type of board) exist for the "same" Minnow Max
|
|
||||||
hardware, so they have to be treated as two different types of hardware. The two
|
|
||||||
examples show you a boot entry specific to a type of board. Titles shown in boot
|
|
||||||
menu have different names according to the type of running board, "Minnow Max
|
|
||||||
boot" or "Minnow Max B3 boot". in /proc/cmdline, "console=ttyS0,115200n8" shall
|
|
||||||
be there. Kernel prints logs from 6-pin FTDI serial port on Minnow Max(s). This
|
|
||||||
console setting is in board-specific entries, so you won't see it effective if
|
|
||||||
you select default "boot" entry to boot the device.
|
|
||||||
|
|
||||||
EXAMPLE 3: Board-specific boot entry, global kernel cmdline and installer
|
|
||||||
NUC Gen 6:
|
|
||||||
common/recipes-bsp/rmc/boards/nucgen6
|
|
||||||
This is a combo example with all supported configuration data for NUC Gen 6
|
|
||||||
product. It shows two boot entries in bootloader menu when you boot image on NUC
|
|
||||||
Gen 6 product, with "NUC Gen6" in entry titles. There shall no any "console=" in
|
|
||||||
/proc/cmdline when you boot with either of two "NUC Gen6"entries. We designed it
|
|
||||||
this way because there is no accessible tty port on NUC Gen 6 with housing. The
|
|
||||||
post-install hook is also provided in this example.
|
|
||||||
|
|
||||||
This example also includes a global kernel cmdline fragment KBOOTPARAM. Content
|
|
||||||
of KBOOTPARAM shall be at the end of /proc/cmdline no matter which boot entry
|
|
||||||
you selected to boot NUC Gen6.
|
|
||||||
|
|
||||||
INSTALLER.CONFIG directs installer to create a directory and deploy a file in it
|
|
||||||
when install the image on NUC Gen6.
|
|
||||||
|
|
||||||
Choose "NUC Gen6 install" boot entry to boot shall start installation. Once
|
|
||||||
the device reboots after installation, we can verify the configurations.
|
|
||||||
|
|
||||||
The boot entry "NUC Gen6 boot" shall be shown in boot menu.
|
|
||||||
|
|
||||||
The content of KBOOTPARAM shall be in /proc/cmdline too.
|
|
||||||
|
|
||||||
A directory /etc/mylib/ is created and a file "mylib.conf" is there. The content
|
|
||||||
of that file shall be what we put in mylib.conf in
|
|
||||||
common/recipes-bsp/rmc/boards/nucgen6
|
|
||||||
|
|
||||||
POSTINSTALL.sh shows how we get rid of an error message caused by no serial
|
|
||||||
console available on NUC Gen 6, without creating another static board
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
EXAMPLE 4: For validation only
|
|
||||||
T100 (32bit):
|
|
||||||
common/recipes-bsp/rmc/boards/T100-32bit
|
|
||||||
This example is provided for validation on 32 bit X86 architecture. It doesn't
|
|
||||||
provide any new function not mentioned in above examples.
|
|
||||||
|
|
||||||
Troubleshooting
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
Issue: Cannot obtain RMC fingerprint for a board
|
|
||||||
|
|
||||||
RMC tool requires UEFI BIOS and SMBIOS support in firmware. It doesn't support
|
|
||||||
other type of firmware, e.g. legacy BIOS. It also requires EFI driver enabled
|
|
||||||
in Linux kernel.
|
|
||||||
|
|
||||||
Issue: Configuration for a board seems not effective at runtime.
|
|
||||||
|
|
||||||
Check if board is booted from the storage where the image or installation lives
|
|
||||||
when you have multiple boot options in BIOS. On some old hardwares it is not
|
|
||||||
that obvious as you assume. A build image can support boot from both of legacy
|
|
||||||
and UEFI mode, but RMC only works with UEFI boot so far.
|
|
||||||
|
|
||||||
Make sure configuration files (BOOTENTRY.CONFIG, INSTALLER.CONFIG and,
|
|
||||||
KBOOTPARAM ...) are properly named in the board directory.
|
|
||||||
|
|
||||||
Make sure configuration files have correct contents.
|
|
||||||
|
|
||||||
Some file attributes could not be supported by targeted file system. Installer
|
|
||||||
cannot setup file blobs as you wish. It simply move to the next step if a step
|
|
||||||
fails.
|
|
||||||
|
|
||||||
Kernel command line can be customized globally with KBOOTPARAM or just in a boot
|
|
||||||
entry for the type of board. They have different effective scopes.
|
|
||||||
|
|
||||||
If no any board-specific configuration becomes effective on your board but it
|
|
||||||
works on other boards of same product, you can run rmc tool to obtain
|
|
||||||
fingerprint file on your board and compare it with fingerprint of a working
|
|
||||||
board. It is possible they have different firmware versions and unluckily, some
|
|
||||||
information for fingerprint changes between two versions. You can update BIOS
|
|
||||||
on every board to the same BIOS version if it is feasible. Otherwise you have
|
|
||||||
to treat them as two different type of boards. We could extend rmc design to
|
|
||||||
allow multiple fingerprints in a board directory as a workaround.
|
|
||||||
|
|
||||||
Issue: RMC reports error because it cannot find fingerprint when building image.
|
|
||||||
|
|
||||||
Make sure you have a fingerprint file. Its name must be ended with '.fp'. You
|
|
||||||
can put a fingerprint file in a board directory and provide data later.
|
|
||||||
|
|
||||||
Issue: Any problems the above troubleshooting cannot help
|
|
||||||
|
|
||||||
Please report it to us. Extra information like the type of your board or a dump
|
|
||||||
file from dmidecode tool is helpful. We will investigate the problem and keep
|
|
||||||
improving this feature.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
When you (don't) need RMC feature
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
RMC feature is designed to as generic as possible, in order to support a large
|
|
||||||
number of types of boards. And it shall be designed not to break things when it
|
|
||||||
is disabled. These considerations help users to decide if they really need or
|
|
||||||
enable it.
|
|
||||||
|
|
||||||
If you are satisfied with a dedicated build target and image for each board in
|
|
||||||
your development cycle (source, build, validation, release, etc), you don't need
|
|
||||||
this feature.
|
|
||||||
|
|
||||||
If you have a generic build for multiple type of boards and features supported
|
|
||||||
by that build meet your needs to functionality on all of boards, you don't need
|
|
||||||
to have this feature or you can disable it until you need to check in the first
|
|
||||||
board's data, in order to apply a quirk or customization only for that board.
|
|
||||||
|
|
||||||
If you want this feature but have concerns to see more and more boards' finger-
|
|
||||||
prints and data in a generic project, you can have another layer to hold all of
|
|
||||||
board-specific data to split them from a generic layer at source level. Another
|
|
||||||
suggestion is always seeking chances not to clone or copy a common configuration
|
|
||||||
to each board's directory.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Thanks
|
|
||||||
|
|
||||||
Jianxun Zhang <jianxun.zhang@linux.intel.com>
|
|
|
@ -1 +0,0 @@
|
||||||
console=ttyS0,115200
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,2 +0,0 @@
|
||||||
efi_entry_dir:root:disk:770:/boot/loader/entries/
|
|
||||||
boot.conf:root:disk:770:/boot/loader/entries/rmcboot.conf
|
|
|
@ -1,2 +0,0 @@
|
||||||
# There is no tty device on this board.
|
|
||||||
sed -i '/start_getty.\+ttyS.*/d' /tgt_root/etc/inittab
|
|
|
@ -1,4 +0,0 @@
|
||||||
title NUC5i5RYB boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot rootwait
|
|
|
@ -1,4 +0,0 @@
|
||||||
title NUC5i5RYB install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi rootwait
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
Binary file not shown.
|
@ -1,4 +0,0 @@
|
||||||
title T100T(32bit) boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot loglevel=8
|
|
|
@ -1,4 +0,0 @@
|
||||||
title T100T(32bit) install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi
|
|
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Keep rmc Joule boot.conf instead of meta-intel default
|
|
||||||
efi_entry_dir:root:disk:770:/boot/loader/entries/
|
|
||||||
boot.conf:root:disk:770:/boot/loader/entries/boot.conf
|
|
|
@ -1 +0,0 @@
|
||||||
video=efifb maxcpus=4 reboot=efi kmemleak=off console=tty0 console=ttyS2,115200
|
|
|
@ -1,2 +0,0 @@
|
||||||
# Joule uses only S2 for serial, so remove S0
|
|
||||||
sed -i '/start_getty.\+ttyS0/d' /tgt_root/etc/inittab
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,4 +0,0 @@
|
||||||
title Joule / Broxton-m
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Joule / Broxton-m Install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi rootwait
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Minnow Max boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot console=ttyS0,115200n8
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Minnow Max install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi console=ttyS0,115200n8
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Minnow Max B3 boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot console=ttyS0,115200n8
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Minnow Max B3 install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi console=ttyS0,115200n8
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Keep rmc Mohonpeak boot.conf instead of meta-intel default
|
|
||||||
efi_entry_dir:root:disk:770:/boot/loader/entries/
|
|
||||||
boot.conf:root:disk:770:/boot/loader/entries/boot.conf
|
|
|
@ -1 +0,0 @@
|
||||||
console=ttyS1,115200 console=tty1
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Mohonpeak uses only S1 for serial, so remove S0 and S2
|
|
||||||
sed -i '/start_getty.\+ttyS0/d' /tgt_root/etc/inittab
|
|
||||||
sed -i '/start_getty.\+ttyS2/d' /tgt_root/etc/inittab
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Mohon Peak boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot
|
|
|
@ -1,4 +0,0 @@
|
||||||
title Mohon Peak Install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi rootwait
|
|
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
|
@ -1,6 +0,0 @@
|
||||||
# This file specifies which file or dir RMC will install onto target.
|
|
||||||
# Note the absolute path is referred from mount points in installation.
|
|
||||||
efi_entry_dir:root:disk:770:/boot/loader/entries/
|
|
||||||
boot.conf:root:disk:770:/boot/loader/entries/rmcboot.conf
|
|
||||||
mylibdir:root:root:770:/tgt_root/etc/mylib/
|
|
||||||
mylib.conf:root:root:660:/tgt_root/etc/mylib/mylib.conf
|
|
|
@ -1 +0,0 @@
|
||||||
i915.preliminary_hw_support=1
|
|
|
@ -1,7 +0,0 @@
|
||||||
# NUC Gen 6 specific retouch after RMC deployment
|
|
||||||
|
|
||||||
# The generated inittab from OE build causes error messages:
|
|
||||||
# "auth.err getty[615]: tcgetattr: Input/output error"
|
|
||||||
# in /var/log/messages because NUC Gen 6 doesn't have any
|
|
||||||
# serial tty. We delete line(s) here on target.
|
|
||||||
sed -i '/start_getty.\+ttyS.*/d' /tgt_root/etc/inittab
|
|
|
@ -1,4 +0,0 @@
|
||||||
title NUC Gen6 boot
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=boot
|
|
|
@ -1,4 +0,0 @@
|
||||||
title NUC Gen6 install
|
|
||||||
linux /vmlinuz
|
|
||||||
initrd /initrd
|
|
||||||
options LABEL=install-efi
|
|
|
@ -1,7 +0,0 @@
|
||||||
# This is a demo conf file read by an imagined program or library
|
|
||||||
# which reads this file at runtime to customize its behavior.
|
|
||||||
# rmc will deploy it to the location specified in INSTALLER.CONFIG.
|
|
||||||
|
|
||||||
lib.info = "V1.0 for rmc demo"
|
|
||||||
lib.board = "NUC gen 6"
|
|
||||||
prog.ui.layout = "minimal"
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
console=ttyS0,115200
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
console=ttyS0,115200
|
|
Binary file not shown.
|
@ -1,62 +0,0 @@
|
||||||
SUMMARY = "Central RMC Database"
|
|
||||||
DESCRIPTION = "Generate a centralized RMC database for RMC feature. \
|
|
||||||
Fingerprints and data for all boards supported are specified by variable \
|
|
||||||
RMC_BOARD_DATA_DIRS which is a list of top directories that contains \
|
|
||||||
subdirectories for boards. Developers can add their top directories by appending \
|
|
||||||
them to this variable in a rmc-db.bbappend.Refer to rmc-db bbclass for more \
|
|
||||||
information."
|
|
||||||
|
|
||||||
LICENSE = "MIT"
|
|
||||||
|
|
||||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
|
|
||||||
|
|
||||||
S = "${WORKDIR}"
|
|
||||||
|
|
||||||
inherit rmc-db
|
|
||||||
|
|
||||||
RMC_BOARD_DATA_DIRS ?= "${THISDIR}/boards/"
|
|
||||||
RMC_DB_DIR = "${WORKDIR}/db"
|
|
||||||
|
|
||||||
FILES_${PN} = "/boot/rmc.db"
|
|
||||||
|
|
||||||
# Let sstate be aware of change in any added board directories
|
|
||||||
do_generate_rmc_db[file-checksums] = "${@get_rmc_top_dirs_list(d)}"
|
|
||||||
|
|
||||||
# derived from get_lic_checksum_file_list(d) in base.bbclass in OE
|
|
||||||
def get_rmc_top_dirs_list(d):
|
|
||||||
dirlist = []
|
|
||||||
dirs = d.getVar("RMC_BOARD_DATA_DIRS", True) or ''
|
|
||||||
topdirs = dirs.split()
|
|
||||||
for each in topdirs:
|
|
||||||
dirlist.append(each + ":" + str(os.path.exists(each)))
|
|
||||||
return " ".join(dirlist)
|
|
||||||
|
|
||||||
do_generate_rmc_db () {
|
|
||||||
rmc_generate_db "${RMC_BOARD_DATA_DIRS}" "${RMC_DB_DIR}"/rmc.db
|
|
||||||
}
|
|
||||||
|
|
||||||
addtask generate_rmc_db after do_compile
|
|
||||||
|
|
||||||
inherit deploy
|
|
||||||
|
|
||||||
do_deploy () {
|
|
||||||
if [ -f ${RMC_DB_DIR}/rmc.db ]; then
|
|
||||||
install -m 0400 ${RMC_DB_DIR}/rmc.db ${DEPLOYDIR}
|
|
||||||
else
|
|
||||||
rm -f ${DEPLOYDIR}/rmc.db
|
|
||||||
echo "Warning: no RMC central database found, skip deployment."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
do_install () {
|
|
||||||
install -d ${D}/boot
|
|
||||||
if [ -f ${RMC_DB_DIR}/rmc.db ]; then
|
|
||||||
install -m 0400 ${RMC_DB_DIR}/rmc.db ${D}/boot/
|
|
||||||
else
|
|
||||||
rm -f ${D}/rmc.db
|
|
||||||
echo "Warning: no RMC central database found, skip installation."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
do_install[depends] += "${PN}:do_generate_rmc_db"
|
|
||||||
|
|
||||||
addtask deploy after do_generate_rmc_db
|
|
|
@ -1,40 +0,0 @@
|
||||||
SUMMARY = "RMC (Runtime Machine Configuration) EFI library"
|
|
||||||
|
|
||||||
DESCRIPTION = "The RMC EFI library adds RMC support to existing EFI bootloaders"
|
|
||||||
|
|
||||||
LICENSE = "MIT"
|
|
||||||
|
|
||||||
LIC_FILES_CHKSUM = "file://COPYING;md5=ade413c694d3aaefc9554b24a8814ee8"
|
|
||||||
|
|
||||||
SRC_URI = "git://git.yoctoproject.org/rmc"
|
|
||||||
|
|
||||||
SRCREV = "027ac76f642dcab1a9f237a00f03a3a714bd04b9"
|
|
||||||
|
|
||||||
S = "${WORKDIR}/git"
|
|
||||||
|
|
||||||
COMPATIBLE_HOST = "(x86_64.*|i.86.*)-linux*"
|
|
||||||
|
|
||||||
TARGET_CFLAGS +="-Wl,--hash-style=both"
|
|
||||||
|
|
||||||
EXTRA_OEMAKE = "RMC_INSTALL_PREFIX=${D}/${prefix} \
|
|
||||||
RMC_INSTALL_LIB_PATH=${D}${libdir} \
|
|
||||||
RMC_INSTALL_HEADER_PATH=${D}${includedir}/rmc"
|
|
||||||
|
|
||||||
SECURITY_CFLAGS_remove_class-target = "-fstack-protector-strong"
|
|
||||||
SECURITY_CFLAGS_append_class-target = " -fno-stack-protector"
|
|
||||||
|
|
||||||
python () {
|
|
||||||
ccargs = d.getVar('TUNE_CCARGS').split()
|
|
||||||
if '-mx32' in ccargs:
|
|
||||||
ccargs.remove('-mx32')
|
|
||||||
ccargs.append('-m64')
|
|
||||||
d.setVar('TUNE_CCARGS', ' '.join(ccargs))
|
|
||||||
}
|
|
||||||
|
|
||||||
do_compile() {
|
|
||||||
oe_runmake -f Makefile.efi
|
|
||||||
}
|
|
||||||
|
|
||||||
do_install() {
|
|
||||||
oe_runmake -f Makefile.efi install
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
SUMMARY = "RMC (Runtime Machine Configuration)"
|
|
||||||
|
|
||||||
DESCRIPTION = "RMC project provides a tool and libraries to identify types \
|
|
||||||
of hardware boards and access any file-based data specific to the board's \
|
|
||||||
type at runtime in a centralized way. Software (clients) can have a generic \
|
|
||||||
logic to query board-specific data from RMC without knowing the type of board. \
|
|
||||||
This make it possible to have a generic software work running on boards which \
|
|
||||||
require any quirks or customizations at a board or product level. \
|
|
||||||
"
|
|
||||||
|
|
||||||
LICENSE = "MIT"
|
|
||||||
|
|
||||||
LIC_FILES_CHKSUM = "file://COPYING;md5=ade413c694d3aaefc9554b24a8814ee8"
|
|
||||||
|
|
||||||
SRC_URI = "git://git.yoctoproject.org/rmc"
|
|
||||||
|
|
||||||
SRCREV = "027ac76f642dcab1a9f237a00f03a3a714bd04b9"
|
|
||||||
|
|
||||||
S = "${WORKDIR}/git"
|
|
||||||
|
|
||||||
COMPATIBLE_HOST = "(x86_64.*|i.86.*)-linux*"
|
|
||||||
|
|
||||||
TARGET_CFLAGS +="-Wl,--hash-style=both"
|
|
||||||
|
|
||||||
EXTRA_OEMAKE = "RMC_INSTALL_PREFIX=${D}/${prefix} \
|
|
||||||
RMC_INSTALL_BIN_PATH=${D}${bindir} \
|
|
||||||
RMC_INSTALL_LIB_PATH=${D}${libdir} \
|
|
||||||
RMC_INSTALL_HEADER_PATH=${D}${includedir}/rmc"
|
|
||||||
|
|
||||||
SECURITY_CFLAGS_remove_class-target = "-fstack-protector-strong"
|
|
||||||
SECURITY_CFLAGS_append_class-target = " -fno-stack-protector"
|
|
||||||
|
|
||||||
do_compile_class-target() {
|
|
||||||
oe_runmake
|
|
||||||
}
|
|
||||||
|
|
||||||
do_install() {
|
|
||||||
oe_runmake install
|
|
||||||
}
|
|
||||||
|
|
||||||
do_install_class-native() {
|
|
||||||
install -d ${D}${STAGING_BINDIR_NATIVE}
|
|
||||||
install -m 0755 ${S}/src/rmc ${D}${STAGING_BINDIR_NATIVE}
|
|
||||||
}
|
|
||||||
|
|
||||||
BBCLASSEXTEND = "native"
|
|
|
@ -1,46 +0,0 @@
|
||||||
From beb095f41d458b7d684c0cd6cac1749e2fc3f29b Mon Sep 17 00:00:00 2001
|
|
||||||
From: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
Date: Wed, 21 Mar 2018 13:01:26 -0700
|
|
||||||
Subject: [PATCH 1/5] partially revert "sd-boot: stub: Obtain PE section
|
|
||||||
offsets from RAM, not disk (#6250)"
|
|
||||||
|
|
||||||
Only revert the section for finding the root_dir, as RMC needs this to
|
|
||||||
find its database file.
|
|
||||||
|
|
||||||
Upstream-Status: Inappropriate [upstream doesn't need the root_dir].
|
|
||||||
|
|
||||||
Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
---
|
|
||||||
src/boot/efi/stub.c | 9 +++++++++
|
|
||||||
1 file changed, 9 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
|
||||||
index ff45cebd4..540ca5985 100644
|
|
||||||
--- a/src/boot/efi/stub.c
|
|
||||||
+++ b/src/boot/efi/stub.c
|
|
||||||
@@ -30,6 +30,8 @@ static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
|
|
||||||
|
|
||||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
EFI_LOADED_IMAGE *loaded_image;
|
|
||||||
+ EFI_FILE *root_dir;
|
|
||||||
+ CHAR16 *loaded_image_path;
|
|
||||||
CHAR8 *b;
|
|
||||||
UINTN size;
|
|
||||||
BOOLEAN secure = FALSE;
|
|
||||||
@@ -58,6 +60,13 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ root_dir = LibOpenRoot(loaded_image->DeviceHandle);
|
|
||||||
+ if (!root_dir) {
|
|
||||||
+ Print(L"Unable to open root directory: %r ", err);
|
|
||||||
+ uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
|
|
||||||
+ return EFI_LOAD_ERROR;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS) {
|
|
||||||
if (*b > 0)
|
|
||||||
secure = TRUE;
|
|
||||||
--
|
|
||||||
2.14.3
|
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
From af977853ab722194c4754e6693f430f50a42190f Mon Sep 17 00:00:00 2001
|
|
||||||
From: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
Date: Tue, 20 Mar 2018 10:08:14 -0700
|
|
||||||
Subject: [PATCH 2/5] sd-boot: fix RMC compatibility with systemd-boot and
|
|
||||||
meson
|
|
||||||
|
|
||||||
With autotools swapped out for meson a number of things need to be
|
|
||||||
changed.
|
|
||||||
|
|
||||||
Upstream-Status: Pending
|
|
||||||
|
|
||||||
Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
---
|
|
||||||
meson_options.txt | 2 ++
|
|
||||||
src/boot/efi/meson.build | 4 +++-
|
|
||||||
2 files changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/meson_options.txt b/meson_options.txt
|
|
||||||
index 39822d6cd..d8a480401 100644
|
|
||||||
--- a/meson_options.txt
|
|
||||||
+++ b/meson_options.txt
|
|
||||||
@@ -279,6 +279,8 @@ option('efi-ldsdir', type : 'string',
|
|
||||||
description : 'path to the EFI lds directory')
|
|
||||||
option('efi-includedir', type : 'string', value : '/usr/include/efi',
|
|
||||||
description : 'path to the EFI header directory')
|
|
||||||
+option('rmc-includedir', type : 'string', value : '/usr/include/rmc',
|
|
||||||
+ description : 'path to the RMC header directory')
|
|
||||||
option('tpm-pcrindex', type : 'string', value : '8',
|
|
||||||
description : 'TPM PCR register number to use')
|
|
||||||
|
|
||||||
diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build
|
|
||||||
index 9f9ec4911..266ff928f 100644
|
|
||||||
--- a/src/boot/efi/meson.build
|
|
||||||
+++ b/src/boot/efi/meson.build
|
|
||||||
@@ -83,6 +83,7 @@ if have_gnu_efi
|
|
||||||
efi_conf.set_quoted('EFI_MACHINE_TYPE_NAME', EFI_MACHINE_TYPE_NAME)
|
|
||||||
efi_conf.set10('ENABLE_TPM', get_option('tpm'))
|
|
||||||
efi_conf.set('SD_TPM_PCR', get_option('tpm-pcrindex'))
|
|
||||||
+ efi_conf.set('RMC_EFI', 'true')
|
|
||||||
|
|
||||||
efi_config_h = configure_file(
|
|
||||||
output : 'efi_config.h',
|
|
||||||
@@ -121,6 +122,7 @@ if have_gnu_efi
|
|
||||||
'-Wsign-compare',
|
|
||||||
'-Wno-missing-field-initializers',
|
|
||||||
'-isystem', efi_incdir,
|
|
||||||
+ '-isystem', get_option('rmc-includedir'),
|
|
||||||
'-isystem', join_paths(efi_incdir, gnu_efi_arch),
|
|
||||||
'-include', efi_config_h]
|
|
||||||
if efi_arch == 'x86_64'
|
|
||||||
@@ -191,7 +193,7 @@ if have_gnu_efi
|
|
||||||
output : tuple[0],
|
|
||||||
command : efi_ld.split() + ['-o', '@OUTPUT@'] +
|
|
||||||
efi_ldflags + tuple[2] +
|
|
||||||
- ['-lefi', '-lgnuefi', libgcc_file_name])
|
|
||||||
+ ['-lefi', '-lgnuefi', '-lrmcefi', libgcc_file_name])
|
|
||||||
|
|
||||||
test('no-undefined-symbols-' + tuple[0],
|
|
||||||
no_undefined_symbols,
|
|
||||||
--
|
|
||||||
2.14.3
|
|
||||||
|
|
|
@ -1,252 +0,0 @@
|
||||||
From b780c67c780bae2f834d73017044680fabca4268 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jianxun Zhang <jianxun.zhang@linux.intel.com>
|
|
||||||
Date: Wed, 1 Jun 2016 16:32:22 -0700
|
|
||||||
Subject: [PATCH 3/5] sd-boot: Load board-specific boot entries from RMC
|
|
||||||
database
|
|
||||||
|
|
||||||
RMC provides a centralized database file on ESP. The DB contains
|
|
||||||
fingerprints and any file blobs associated to physical boards.
|
|
||||||
Callers can fetch board-specific data with fingerprint info
|
|
||||||
collected from board at runtime if there is any record matched
|
|
||||||
board's fingerprint.
|
|
||||||
|
|
||||||
To let bootloader know which file blob in RMC should be queried,
|
|
||||||
a special config file BOOTENTRY.CONFIG is defined as:
|
|
||||||
|
|
||||||
boot.conf
|
|
||||||
install.conf
|
|
||||||
|
|
||||||
Bootloader calls RMC APIs and other functions to perform these
|
|
||||||
tasks before it shows boot menu to user:
|
|
||||||
|
|
||||||
(1) Load RMC database file from ESP
|
|
||||||
(2) Collect fingerprint data from board
|
|
||||||
(3) Query BOOTENTRY.CONFIG from RMC DB with fingerprint
|
|
||||||
(4) Parse BOOTENTRY.CONFIG to know names of boot entry files
|
|
||||||
(5) Query boot entry files one by one from RMC DB, and add
|
|
||||||
them into sd-boot config data.
|
|
||||||
|
|
||||||
The final effect is that bootloader will show board-specific
|
|
||||||
boot entries in boot menu to user. User then can choose one
|
|
||||||
of them to boot system with the selected configuration.
|
|
||||||
|
|
||||||
If any of these steps fails, bootloader simply skips loading
|
|
||||||
RMC configs or any entry file not successfully fetched from
|
|
||||||
RMC DB. Once any entry is loaded successfully from RMC DB,
|
|
||||||
bootloader skips loading any boot entries from ESP.
|
|
||||||
|
|
||||||
Upstream-Status: Pending
|
|
||||||
|
|
||||||
Signed-off-by: Jianxun Zhang <jianxun.zhang@linux.intel.com>
|
|
||||||
Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
---
|
|
||||||
src/boot/efi/boot.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
1 file changed, 146 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
|
||||||
index b9c7c8394..93cfaf193 100644
|
|
||||||
--- a/src/boot/efi/boot.c
|
|
||||||
+++ b/src/boot/efi/boot.c
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
|
|
||||||
#include <efi.h>
|
|
||||||
#include <efilib.h>
|
|
||||||
+#include <rmc_api.h>
|
|
||||||
|
|
||||||
#include "console.h"
|
|
||||||
#include "disk.h"
|
|
||||||
@@ -35,6 +36,9 @@ static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot
|
|
||||||
|
|
||||||
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
|
|
||||||
|
|
||||||
+static CHAR8* rmc_db;
|
|
||||||
+static rmc_fingerprint_t *rmc_fp;
|
|
||||||
+
|
|
||||||
enum loader_type {
|
|
||||||
LOADER_UNDEFINED,
|
|
||||||
LOADER_EFI,
|
|
||||||
@@ -1684,6 +1688,136 @@ static VOID config_free(Config *config) {
|
|
||||||
FreePool(config->entry_oneshot);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* Derived from line_get_key_value(), we could consolidate two functions later */
|
|
||||||
+static CHAR8 *get_line(CHAR8 *content, UINT64 *pos) {
|
|
||||||
+ CHAR8 *line;
|
|
||||||
+ UINT64 linelen;
|
|
||||||
+
|
|
||||||
+skip:
|
|
||||||
+ line = content + *pos;
|
|
||||||
+ if (*line == '\0')
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ linelen = 0;
|
|
||||||
+ while (line[linelen] && !strchra((CHAR8 *)"\n\r", line[linelen]))
|
|
||||||
+ linelen++;
|
|
||||||
+
|
|
||||||
+ /* move pos to next line */
|
|
||||||
+ *pos += linelen;
|
|
||||||
+ if (content[*pos])
|
|
||||||
+ (*pos)++;
|
|
||||||
+
|
|
||||||
+ /* empty line */
|
|
||||||
+ if (linelen == 0)
|
|
||||||
+ goto skip;
|
|
||||||
+
|
|
||||||
+ /* terminate line */
|
|
||||||
+ line[linelen] = '\0';
|
|
||||||
+
|
|
||||||
+ /* remove leading whitespace */
|
|
||||||
+ while (strchra((CHAR8 *)" \t", *line)) {
|
|
||||||
+ line++;
|
|
||||||
+ linelen--;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* remove trailing whitespace */
|
|
||||||
+ while (linelen > 0 && strchra((CHAR8 *)" \t", line[linelen-1]))
|
|
||||||
+ linelen--;
|
|
||||||
+ line[linelen] = '\0';
|
|
||||||
+
|
|
||||||
+ if (*line == '#')
|
|
||||||
+ goto skip;
|
|
||||||
+
|
|
||||||
+ return line;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* load rmc database file from ESP and try to get fingerprint. These
|
|
||||||
+ * are essential information indicating we could query rmc data for
|
|
||||||
+ * this board at least
|
|
||||||
+ * return 0 if both database file and fingerprint can be obtained, otherwise
|
|
||||||
+ * non-zero value is returned.
|
|
||||||
+ *
|
|
||||||
+ * Note: db and fp hold valid values only when this function returns 0.
|
|
||||||
+ * Caller is responsible to free allocated memory pointed by *db and *fp when
|
|
||||||
+ * this function returns 0.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+static UINTN rmc_initialize(EFI_FILE *root_dir, EFI_SYSTEM_TABLE *sys_table, CHAR8 **db, rmc_fingerprint_t **fp) {
|
|
||||||
+ UINTN len;
|
|
||||||
+ UINTN ret = 1;
|
|
||||||
+
|
|
||||||
+ if (!db || !fp)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ *db = NULL;
|
|
||||||
+ *fp = NULL;
|
|
||||||
+
|
|
||||||
+ /* load rmc database */
|
|
||||||
+ len = file_read(root_dir, L"\\rmc.db", 0, 0, db);
|
|
||||||
+
|
|
||||||
+ if (len <= 0)
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ *fp = AllocateZeroPool(sizeof(rmc_fingerprint_t));
|
|
||||||
+ /* call rmc to get fingerprint. We will use single-action rmc APIs to query multiple files.
|
|
||||||
+ * This should bring a better performance than calling double-action rmc API every time.
|
|
||||||
+ */
|
|
||||||
+ if (rmc_get_fingerprint(sys_table, *fp))
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ ret = 0;
|
|
||||||
+done:
|
|
||||||
+ if (ret) {
|
|
||||||
+ FreePool(*db);
|
|
||||||
+ FreePool(*fp);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* load RMC entries
|
|
||||||
+ * return TRUE when at least one entry is loaded, otherwise, return FALSE
|
|
||||||
+ */
|
|
||||||
+static BOOLEAN config_load_rmc_entries(Config *config, EFI_HANDLE *device, CHAR16 *loaded_image_path, CHAR8 *db, rmc_fingerprint_t *fp) {
|
|
||||||
+ CHAR8 *boot_entry = NULL;
|
|
||||||
+ CHAR8 *boot_config = NULL;
|
|
||||||
+ rmc_file_t rp;
|
|
||||||
+ CHAR8 *line;
|
|
||||||
+ UINT64 pos = 0;
|
|
||||||
+ BOOLEAN ret = FALSE;
|
|
||||||
+
|
|
||||||
+ if (!db || !fp)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* query boot entry config file */
|
|
||||||
+ if (rmc_query_file_by_fp(fp, db, "BOOTENTRY.CONFIG", &rp))
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* file blob read from rmc db is not necessarily null-terminated, and we
|
|
||||||
+ * should keep mem where rmc db lives from change during parsing
|
|
||||||
+ */
|
|
||||||
+ boot_config = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1);
|
|
||||||
+ CopyMem(boot_config, rp.blob, rp.blob_len);
|
|
||||||
+ boot_config[rp.blob_len] = '\0';
|
|
||||||
+ /* parse boot entry config */
|
|
||||||
+ while ((line = get_line(boot_config, &pos))) {
|
|
||||||
+ if (rmc_query_file_by_fp(fp, db, (char *)line, &rp))
|
|
||||||
+ continue;
|
|
||||||
+ if (rp.blob_len > 0) {
|
|
||||||
+ boot_entry = AllocatePool(rp.blob_len * sizeof(CHAR8) + 1);
|
|
||||||
+ CopyMem(boot_entry, rp.blob, rp.blob_len);
|
|
||||||
+ boot_entry[rp.blob_len] = '\0';
|
|
||||||
+ config_entry_add_from_file(config, device,
|
|
||||||
+ stra_to_str(line), boot_entry,
|
|
||||||
+ loaded_image_path);
|
|
||||||
+ /* tell caller success when a RMC entry is loaded */
|
|
||||||
+ ret = TRUE;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
CHAR16 *s;
|
|
||||||
CHAR8 *b;
|
|
||||||
@@ -1696,6 +1830,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
UINT64 init_usec;
|
|
||||||
BOOLEAN menu = FALSE;
|
|
||||||
CHAR16 uuid[37];
|
|
||||||
+ BOOLEAN rmc_entry = FALSE;
|
|
||||||
|
|
||||||
InitializeLib(image, sys_table);
|
|
||||||
init_usec = time_usec();
|
|
||||||
@@ -1736,6 +1871,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Initialize rmc before loading any config */
|
|
||||||
+ rmc_initialize(root_dir, sys_table, &rmc_db, &rmc_fp);
|
|
||||||
+
|
|
||||||
/* the filesystem path to this image, to prevent adding ourselves to the menu */
|
|
||||||
loaded_image_path = DevicePathToStr(loaded_image->FilePath);
|
|
||||||
efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
|
|
||||||
@@ -1743,11 +1881,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
ZeroMem(&config, sizeof(Config));
|
|
||||||
config_load_defaults(&config, root_dir);
|
|
||||||
|
|
||||||
+ if (rmc_db && rmc_fp)
|
|
||||||
+ rmc_entry = config_load_rmc_entries(&config, loaded_image->DeviceHandle, loaded_image_path, rmc_db, rmc_fp);
|
|
||||||
+
|
|
||||||
/* scan /EFI/Linux/ directory */
|
|
||||||
config_entry_add_linux(&config, loaded_image, root_dir);
|
|
||||||
|
|
||||||
- /* scan /loader/entries/\*.conf files */
|
|
||||||
- config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
|
|
||||||
+ /* scan /loader/entries/\*.conf files only when no RMC entry is loaded */
|
|
||||||
+ if (rmc_entry == FALSE)
|
|
||||||
+ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
|
|
||||||
|
|
||||||
/* sort entries after version number */
|
|
||||||
config_sort_entries(&config);
|
|
||||||
@@ -1841,6 +1983,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
out:
|
|
||||||
FreePool(loaded_image_path);
|
|
||||||
config_free(&config);
|
|
||||||
+ FreePool(rmc_db);
|
|
||||||
+ FreePool(rmc_fp);
|
|
||||||
uefi_call_wrapper(root_dir->Close, 1, root_dir);
|
|
||||||
uefi_call_wrapper(BS->CloseProtocol, 4, image, &LoadedImageProtocol, image, NULL);
|
|
||||||
return err;
|
|
||||||
--
|
|
||||||
2.14.3
|
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
From 159c8c54f92fb44d8abd2919fa83ad1cb640fac3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jianxun Zhang <jianxun.zhang@linux.intel.com>
|
|
||||||
Date: Mon, 20 Jun 2016 13:08:20 -0700
|
|
||||||
Subject: [PATCH 4/5] sd-boot: Support global kernel command line fragment
|
|
||||||
|
|
||||||
Query file blob KBOOTPARAM from RMC. If it exists, we append
|
|
||||||
it to the new linux boot entry's cmdline. A boot entry could
|
|
||||||
be read from a .conf file on ESP, RMC database, or embedded
|
|
||||||
linux image. content in KBOOTPARAM is effective in all of
|
|
||||||
these cases.
|
|
||||||
|
|
||||||
Upstream-Status: Pending
|
|
||||||
|
|
||||||
Signed-off-by: Jianxun Zhang <jianxun.zhang@linux.intel.com>
|
|
||||||
Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
---
|
|
||||||
src/boot/efi/boot.c | 34 ++++++++++++++++++++++++++++++++++
|
|
||||||
1 file changed, 34 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
|
|
||||||
index 93cfaf193..2f400db3c 100644
|
|
||||||
--- a/src/boot/efi/boot.c
|
|
||||||
+++ b/src/boot/efi/boot.c
|
|
||||||
@@ -851,6 +851,40 @@ static VOID config_add_entry(Config *config, ConfigEntry *entry) {
|
|
||||||
config->entries = ReallocatePool(config->entries,
|
|
||||||
sizeof(VOID *) * config->entry_count, sizeof(VOID *) * i);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /* rmc: a linux entry could be added from .conf file or an embedded linux image
|
|
||||||
+ * we put appending global command line here to cover both of two cases.
|
|
||||||
+ */
|
|
||||||
+ if (entry->type == LOADER_LINUX && rmc_db && rmc_fp) {
|
|
||||||
+ rmc_file_t rmc_kp;
|
|
||||||
+
|
|
||||||
+ if (!rmc_query_file_by_fp(rmc_fp, rmc_db, "KBOOTPARAM", &rmc_kp)) {
|
|
||||||
+ CHAR8 *cmdline;
|
|
||||||
+ CHAR16 *s;
|
|
||||||
+ CHAR16 *t;
|
|
||||||
+ CHAR16 *p;
|
|
||||||
+
|
|
||||||
+ cmdline = AllocatePool(rmc_kp.blob_len * sizeof(CHAR8) + 1);
|
|
||||||
+ CopyMem(cmdline, rmc_kp.blob, rmc_kp.blob_len);
|
|
||||||
+ cmdline[rmc_kp.blob_len] = '\0';
|
|
||||||
+ p = stra_to_str(cmdline);
|
|
||||||
+ t = p;
|
|
||||||
+
|
|
||||||
+ while (*t) {
|
|
||||||
+ if (*t == '\n')
|
|
||||||
+ *t = '\0';
|
|
||||||
+ t++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ s = PoolPrint(L"%s %s", entry->options, p);
|
|
||||||
+ FreePool(entry->options);
|
|
||||||
+ FreePool(p);
|
|
||||||
+ FreePool(cmdline);
|
|
||||||
+
|
|
||||||
+ entry->options = s;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
config->entries[config->entry_count++] = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
2.14.3
|
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
From 405a77233dde990fa7815d1546dc5a6b5a608479 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mikko Ylinen <mikko.ylinen@intel.com>
|
|
||||||
Date: Fri, 27 Jan 2017 13:31:45 +0200
|
|
||||||
Subject: [PATCH 5/5] sd-boot: support global kernel command line in EFI stub
|
|
||||||
|
|
||||||
This change integrates rmc into EFI stub and supports a
|
|
||||||
global fragment (RMC KBOOTPARAM) that is appended to the
|
|
||||||
cmdline at boot.
|
|
||||||
|
|
||||||
The fragment is board-specific and read from the database.
|
|
||||||
|
|
||||||
Implements [YOCTO #10924].
|
|
||||||
|
|
||||||
Upstream-status: Pending
|
|
||||||
|
|
||||||
Signed-off-by: Mikko Ylinen <mikko.ylinen@intel.com>
|
|
||||||
Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
|
|
||||||
---
|
|
||||||
src/boot/efi/stub.c | 33 +++++++++++++++++++++++++++++++++
|
|
||||||
1 file changed, 33 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
|
|
||||||
index 540ca5985..11047477b 100644
|
|
||||||
--- a/src/boot/efi/stub.c
|
|
||||||
+++ b/src/boot/efi/stub.c
|
|
||||||
@@ -14,6 +14,7 @@
|
|
||||||
|
|
||||||
#include <efi.h>
|
|
||||||
#include <efilib.h>
|
|
||||||
+#include <rmc_api.h>
|
|
||||||
|
|
||||||
#include "disk.h"
|
|
||||||
#include "graphics.h"
|
|
||||||
@@ -49,6 +50,9 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
UINTN cmdline_len;
|
|
||||||
CHAR16 uuid[37];
|
|
||||||
EFI_STATUS err;
|
|
||||||
+ INTN len;
|
|
||||||
+ CHAR8 *rmc_db = NULL;
|
|
||||||
+ rmc_file_t rmc_file;
|
|
||||||
|
|
||||||
InitializeLib(image, sys_table);
|
|
||||||
|
|
||||||
@@ -109,6 +113,35 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
+ len = file_read(root_dir, L"\\rmc.db", 0, 0, &rmc_db);
|
|
||||||
+ if (len <= 0)
|
|
||||||
+ rmc_db = NULL;
|
|
||||||
+
|
|
||||||
+ /* If the board has a fragment in rmc database, append it to the cmdline */
|
|
||||||
+ if (rmc_db && !rmc_gimme_file(sys_table, rmc_db, "KBOOTPARAM", &rmc_file)) {
|
|
||||||
+ CHAR8 *line;
|
|
||||||
+ UINTN i = 0;
|
|
||||||
+ UINTN j;
|
|
||||||
+
|
|
||||||
+ line = AllocatePool(rmc_file.blob_len + cmdline_len + 2);
|
|
||||||
+
|
|
||||||
+ while (i < cmdline_len && cmdline[i] != '\0') {
|
|
||||||
+ line[i] = cmdline[i];
|
|
||||||
+ i++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ line[i++] = ' ';
|
|
||||||
+
|
|
||||||
+ for (j=0; j < rmc_file.blob_len; j++)
|
|
||||||
+ line[i+j] = rmc_file.blob[j];
|
|
||||||
+ line[i+j] = '\0';
|
|
||||||
+
|
|
||||||
+ cmdline = line;
|
|
||||||
+ cmdline_len = i + j;
|
|
||||||
+
|
|
||||||
+ FreePool(rmc_db);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* export the device path this image is started from */
|
|
||||||
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
|
|
||||||
efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
|
|
||||||
--
|
|
||||||
2.14.3
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
# This patchset contains hooks that allows systemd-boot to use RMC capablilities.
|
|
||||||
python __anonymous () {
|
|
||||||
import re
|
|
||||||
target = d.getVar('TARGET_ARCH')
|
|
||||||
prefix = "" if d.getVar('EFI_PROVIDER') == "rmc-boot" else "systemd-"
|
|
||||||
if target == "x86_64":
|
|
||||||
systemdimage = prefix + "bootx64.efi"
|
|
||||||
else:
|
|
||||||
systemdimage = prefix + "bootia32.efi"
|
|
||||||
d.setVar("SYSTEMD_BOOT_IMAGE", systemdimage)
|
|
||||||
prefix = "systemd-" if prefix == "" else ""
|
|
||||||
d.setVar("SYSTEMD_BOOT_IMAGE_PREFIX", prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
DEPENDS_append_intel-x86-common = " rmc rmc-efi"
|
|
||||||
RDEPENDS_${PN}_append_intel-x86-common = " rmc-db"
|
|
||||||
|
|
||||||
EXTRA_OEMESON_append_intel-x86-common = ' \
|
|
||||||
-Drmc-includedir="${STAGING_INCDIR}/rmc" \
|
|
||||||
'
|
|
||||||
|
|
||||||
SRC_URI_append_intel-x86-common = " \
|
|
||||||
file://0001-partially-revert-sd-boot-stub-Obtain-PE-section-offs.patch \
|
|
||||||
file://0002-sd-boot-fix-RMC-compatibility-with-systemd-boot-and-.patch \
|
|
||||||
file://0003-sd-boot-Load-board-specific-boot-entries-from-RMC-da.patch \
|
|
||||||
file://0004-sd-boot-Support-global-kernel-command-line-fragment.patch \
|
|
||||||
file://0005-sd-boot-support-global-kernel-command-line-in-EFI-st.patch \
|
|
||||||
"
|
|
||||||
|
|
||||||
RPROVIDES_${PN} += "rmc-boot"
|
|
|
@ -13,6 +13,3 @@ do_compile_append_intel-x86-common() {
|
||||||
do_deploy_append_intel-x86-common() {
|
do_deploy_append_intel-x86-common() {
|
||||||
install ${B}/src/boot/efi/linux*.efi.stub ${DEPLOYDIR}
|
install ${B}/src/boot/efi/linux*.efi.stub ${DEPLOYDIR}
|
||||||
}
|
}
|
||||||
|
|
||||||
# includes rmc-boot.inc if rmc-boot is the EFI_PROVIDER
|
|
||||||
include systemd-boot/${EFI_PROVIDER}.inc
|
|
||||||
|
|
|
@ -1,342 +0,0 @@
|
||||||
#!/bin/sh -e
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016, Intel Corporation.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# install.sh [device_name] [rootfs_name]
|
|
||||||
#
|
|
||||||
# This file is a copy of file with same name in OE:
|
|
||||||
# meta/recipes-core/initrdscripts/files/. We modify
|
|
||||||
# it for RMC feature to deploy file blobs from RMC
|
|
||||||
# database file to target.
|
|
||||||
|
|
||||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
|
||||||
|
|
||||||
# We need 20 Mb for the boot partition
|
|
||||||
boot_size=20
|
|
||||||
|
|
||||||
# 5% for swap
|
|
||||||
swap_ratio=5
|
|
||||||
|
|
||||||
# Get a list of hard drives
|
|
||||||
hdnamelist=""
|
|
||||||
live_dev_name=`cat /proc/mounts | grep ${1%/} | awk '{print $1}'`
|
|
||||||
live_dev_name=${live_dev_name#\/dev/}
|
|
||||||
# Only strip the digit identifier if the device is not an mmc
|
|
||||||
case $live_dev_name in
|
|
||||||
mmcblk*)
|
|
||||||
;;
|
|
||||||
nvme*)
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
live_dev_name=${live_dev_name%%[0-9]*}
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "Searching for hard drives ..."
|
|
||||||
|
|
||||||
for device in `ls /sys/block/`; do
|
|
||||||
case $device in
|
|
||||||
loop*)
|
|
||||||
# skip loop device
|
|
||||||
;;
|
|
||||||
sr*)
|
|
||||||
# skip CDROM device
|
|
||||||
;;
|
|
||||||
ram*)
|
|
||||||
# skip ram device
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
# skip the device LiveOS is on
|
|
||||||
# Add valid hard drive name to the list
|
|
||||||
case $device in
|
|
||||||
$live_dev_name*)
|
|
||||||
# skip the device we are running from
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
hdnamelist="$hdnamelist $device"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "${hdnamelist}" ]; then
|
|
||||||
echo "You need another device (besides the live device /dev/${live_dev_name}) to install the image. Installation aborted."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
TARGET_DEVICE_NAME=""
|
|
||||||
for hdname in $hdnamelist; do
|
|
||||||
# Display found hard drives and their basic info
|
|
||||||
echo "-------------------------------"
|
|
||||||
echo /dev/$hdname
|
|
||||||
if [ -r /sys/block/$hdname/device/vendor ]; then
|
|
||||||
echo -n "VENDOR="
|
|
||||||
cat /sys/block/$hdname/device/vendor
|
|
||||||
fi
|
|
||||||
if [ -r /sys/block/$hdname/device/model ]; then
|
|
||||||
echo -n "MODEL="
|
|
||||||
cat /sys/block/$hdname/device/model
|
|
||||||
fi
|
|
||||||
if [ -r /sys/block/$hdname/device/uevent ]; then
|
|
||||||
echo -n "UEVENT="
|
|
||||||
cat /sys/block/$hdname/device/uevent
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
done
|
|
||||||
|
|
||||||
# Get user choice
|
|
||||||
while true; do
|
|
||||||
echo "Please select an install target or press n to exit ($hdnamelist ): "
|
|
||||||
read answer
|
|
||||||
if [ "$answer" = "n" ]; then
|
|
||||||
echo "Installation manually aborted."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
for hdname in $hdnamelist; do
|
|
||||||
if [ "$answer" = "$hdname" ]; then
|
|
||||||
TARGET_DEVICE_NAME=$answer
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [ -n "$TARGET_DEVICE_NAME" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -n "$TARGET_DEVICE_NAME" ]; then
|
|
||||||
echo "Installing image on /dev/$TARGET_DEVICE_NAME ..."
|
|
||||||
else
|
|
||||||
echo "No hard drive selected. Installation aborted."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
device=/dev/$TARGET_DEVICE_NAME
|
|
||||||
|
|
||||||
#
|
|
||||||
# The udev automounter can cause pain here, kill it
|
|
||||||
#
|
|
||||||
rm -f /etc/udev/rules.d/automount.rules
|
|
||||||
rm -f /etc/udev/scripts/mount*
|
|
||||||
|
|
||||||
#
|
|
||||||
# Unmount anything the automounter had mounted
|
|
||||||
#
|
|
||||||
umount ${device}* 2> /dev/null || /bin/true
|
|
||||||
|
|
||||||
mkdir -p /tmp
|
|
||||||
|
|
||||||
# Create /etc/mtab if not present
|
|
||||||
if [ ! -e /etc/mtab ]; then
|
|
||||||
cat /proc/mounts > /etc/mtab
|
|
||||||
fi
|
|
||||||
|
|
||||||
disk_size=$(parted ${device} unit mb print | grep '^Disk .*: .*MB' | cut -d" " -f 3 | sed -e "s/MB//")
|
|
||||||
|
|
||||||
swap_size=$((disk_size*swap_ratio/100))
|
|
||||||
rootfs_size=$((disk_size-boot_size-swap_size))
|
|
||||||
|
|
||||||
rootfs_start=$((boot_size))
|
|
||||||
rootfs_end=$((rootfs_start+rootfs_size))
|
|
||||||
swap_start=$((rootfs_end))
|
|
||||||
|
|
||||||
# MMC devices are special in a couple of ways
|
|
||||||
# 1) they use a partition prefix character 'p'
|
|
||||||
# 2) they are detected asynchronously (need rootwait)
|
|
||||||
rootwait=""
|
|
||||||
part_prefix=""
|
|
||||||
if [ ! "${device#/dev/mmcblk}" = "${device}" ] || \
|
|
||||||
[ ! "${device#/dev/nvme}" = "${device}" ]; then
|
|
||||||
part_prefix="p"
|
|
||||||
rootwait="rootwait"
|
|
||||||
fi
|
|
||||||
bootfs=${device}${part_prefix}1
|
|
||||||
rootfs=${device}${part_prefix}2
|
|
||||||
swap=${device}${part_prefix}3
|
|
||||||
|
|
||||||
echo "*****************"
|
|
||||||
echo "Boot partition size: $boot_size MB ($bootfs)"
|
|
||||||
echo "Rootfs partition size: $rootfs_size MB ($rootfs)"
|
|
||||||
echo "Swap partition size: $swap_size MB ($swap)"
|
|
||||||
echo "*****************"
|
|
||||||
echo "Deleting partition table on ${device} ..."
|
|
||||||
dd if=/dev/zero of=${device} bs=512 count=35
|
|
||||||
|
|
||||||
echo "Creating new partition table on ${device} ..."
|
|
||||||
parted ${device} mklabel gpt
|
|
||||||
|
|
||||||
echo "Creating boot partition on $bootfs"
|
|
||||||
parted ${device} mkpart boot fat32 0% $boot_size
|
|
||||||
parted ${device} set 1 boot on
|
|
||||||
|
|
||||||
echo "Creating rootfs partition on $rootfs"
|
|
||||||
parted ${device} mkpart root ext3 $rootfs_start $rootfs_end
|
|
||||||
|
|
||||||
echo "Creating swap partition on $swap"
|
|
||||||
parted ${device} mkpart swap linux-swap $swap_start 100%
|
|
||||||
|
|
||||||
parted ${device} print
|
|
||||||
|
|
||||||
echo "Formatting $bootfs to vfat..."
|
|
||||||
mkfs.vfat $bootfs
|
|
||||||
|
|
||||||
echo "Formatting $rootfs to ext3..."
|
|
||||||
mkfs.ext3 $rootfs
|
|
||||||
|
|
||||||
echo "Formatting swap partition...($swap)"
|
|
||||||
mkswap $swap
|
|
||||||
|
|
||||||
mkdir /tgt_root
|
|
||||||
mkdir /src_root
|
|
||||||
mkdir -p /boot
|
|
||||||
|
|
||||||
# Handling of the target root partition
|
|
||||||
mount $rootfs /tgt_root
|
|
||||||
mount -o rw,loop,noatime,nodiratime /run/media/$1/$2 /src_root
|
|
||||||
echo "Copying rootfs files..."
|
|
||||||
cp -a /src_root/* /tgt_root
|
|
||||||
if [ -d /tgt_root/etc/ ] ; then
|
|
||||||
boot_uuid=$(blkid -o value -s UUID ${bootfs})
|
|
||||||
swap_part_uuid=$(blkid -o value -s PARTUUID ${swap})
|
|
||||||
echo "/dev/disk/by-partuuid/$swap_part_uuid swap swap defaults 0 0" >> /tgt_root/etc/fstab
|
|
||||||
echo "UUID=$boot_uuid /boot vfat defaults 1 2" >> /tgt_root/etc/fstab
|
|
||||||
# We dont want udev to mount our root device while we're booting...
|
|
||||||
if [ -d /tgt_root/etc/udev/ ] ; then
|
|
||||||
echo "${device}" >> /tgt_root/etc/udev/mount.blacklist
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Handling of the target boot partition
|
|
||||||
mount $bootfs /boot
|
|
||||||
echo "Preparing boot partition..."
|
|
||||||
|
|
||||||
EFIDIR="/boot/EFI/BOOT"
|
|
||||||
mkdir -p $EFIDIR
|
|
||||||
# Copy the efi loader
|
|
||||||
cp /run/media/$1/EFI/BOOT/*.efi $EFIDIR
|
|
||||||
|
|
||||||
# RMC deployment
|
|
||||||
RMC_CMD=/src_root/usr/bin/rmc
|
|
||||||
RMC_DB=/run/media/$1/rmc.db
|
|
||||||
|
|
||||||
# We don't want to quit when a step failed. For example,
|
|
||||||
# a file system could not support some operations.
|
|
||||||
set +e
|
|
||||||
|
|
||||||
if [ -f "${RMC_DB}" ] && [ -f "${RMC_CMD}" ]; then
|
|
||||||
echo "Found RMC database and tool, start RMC deployment"
|
|
||||||
# query INSTALLER.CONFIG from RMC DB
|
|
||||||
if ${RMC_CMD} -B INSTALLER.CONFIG -d "${RMC_DB}" -o /tmp/installer.config; then
|
|
||||||
while IFS=':' read -r NAME TGT_UID TGT_GID TGT_MODE TGT_PATH; do
|
|
||||||
# skip comment
|
|
||||||
# The regexp in grep works with busybox grep which doesn't
|
|
||||||
# seem to have a -P to recognize '\t'. But this expression could not
|
|
||||||
# work with gnu grep...
|
|
||||||
if echo "$NAME"|grep -q $'^[ \t]*#'; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
# check if we should create a directory (last char in target path is '/')
|
|
||||||
# or deploy a file
|
|
||||||
LAST_CHAR=$(echo "${TGT_PATH:$((${#TGT_PATH}-1)):1}")
|
|
||||||
|
|
||||||
# Do not bail out for failures but user should get stderr message
|
|
||||||
if [ ${LAST_CHAR} = "/" ]; then
|
|
||||||
# name field is skipped for directory
|
|
||||||
echo "DIR: ${TGT_UID}:${TGT_GID}:${TGT_MODE} => ${TGT_PATH}"
|
|
||||||
mkdir -p "$TGT_PATH"
|
|
||||||
chown "${TGT_UID}:${TGT_GID}" "$TGT_PATH"
|
|
||||||
chmod "${TGT_MODE}" "$TGT_PATH"
|
|
||||||
else
|
|
||||||
${RMC_CMD} -B "${NAME}" -d "${RMC_DB}" -o "${TGT_PATH}"
|
|
||||||
echo "FILE: ${NAME}:${TGT_UID}:${TGT_GID}:${TGT_MODE} => ${TGT_PATH}"
|
|
||||||
chown "${TGT_UID}:${TGT_GID}" "$TGT_PATH"
|
|
||||||
chmod "${TGT_MODE}" "$TGT_PATH"
|
|
||||||
fi
|
|
||||||
done < /tmp/installer.config
|
|
||||||
rm -rf /tmp/installer.config
|
|
||||||
|
|
||||||
# remove rmc from target since we don't think it is a valid
|
|
||||||
# case to run rmc after installation.
|
|
||||||
rm -rf /tgt_root/usr/bin/rmc
|
|
||||||
echo "RMC deployment finished"
|
|
||||||
else
|
|
||||||
echo "INSTALLER.CONFIG is not found, skip RMC deployment"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Final retouching by calling post-install hook
|
|
||||||
if ${RMC_CMD} -B POSTINSTALL.sh -d "${RMC_DB}" -o /tmp/POSTINSTALL.sh; then
|
|
||||||
echo "Found POSTINSTALL.sh execute it..."
|
|
||||||
chmod 500 /tmp/POSTINSTALL.sh
|
|
||||||
/tmp/POSTINSTALL.sh
|
|
||||||
rm -rf /tmp/POSTINSTALL.sh
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ -f /run/media/$1/EFI/BOOT/grub.cfg ]; then
|
|
||||||
root_part_uuid=$(blkid -o value -s PARTUUID ${rootfs})
|
|
||||||
GRUBCFG="$EFIDIR/grub.cfg"
|
|
||||||
cp /run/media/$1/EFI/BOOT/grub.cfg $GRUBCFG
|
|
||||||
# Update grub config for the installed image
|
|
||||||
# Delete the install entry
|
|
||||||
sed -i "/menuentry 'install'/,/^}/d" $GRUBCFG
|
|
||||||
# Delete the initrd lines
|
|
||||||
sed -i "/initrd /d" $GRUBCFG
|
|
||||||
# Delete any LABEL= strings
|
|
||||||
sed -i "s/ LABEL=[^ ]*/ /" $GRUBCFG
|
|
||||||
# Delete any root= strings
|
|
||||||
sed -i "s/ root=[^ ]*/ /g" $GRUBCFG
|
|
||||||
# Add the root= and other standard boot options
|
|
||||||
sed -i "s@linux /vmlinuz *@linux /vmlinuz root=PARTUUID=$root_part_uuid rw $rootwait quiet @" $GRUBCFG
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d /run/media/$1/loader ]; then
|
|
||||||
rootuuid=$(blkid -o value -s PARTUUID ${rootfs})
|
|
||||||
GUMMIBOOT_CFGS="/boot/loader/entries/*.conf"
|
|
||||||
if [ -d /boot/loader ]; then
|
|
||||||
# Don't override loader.conf RMC already deployed
|
|
||||||
if [ ! -f /boot/loader/loader.conf ]; then
|
|
||||||
cp /run/media/$1/loader/loader.conf /boot/loader/
|
|
||||||
fi
|
|
||||||
# only copy built OE entries when RMC entries don't exist.
|
|
||||||
if [ ! -d /boot/loader/entries ] || [ ! ls /boot/loader/entries/*.conf &>/dev/null ]; then
|
|
||||||
cp -dr /run/media/$1/loader/entries /boot/loader
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# copy config files for gummiboot
|
|
||||||
cp -dr /run/media/$1/loader /boot
|
|
||||||
# delete the install entry
|
|
||||||
rm -f /boot/loader/entries/install.conf
|
|
||||||
fi
|
|
||||||
# delete the initrd lines
|
|
||||||
sed -i "/initrd /d" $GUMMIBOOT_CFGS
|
|
||||||
# delete any LABEL= strings
|
|
||||||
sed -i "s/ LABEL=[^ ]*/ /" $GUMMIBOOT_CFGS
|
|
||||||
# delete any root= strings
|
|
||||||
sed -i "s/ root=[^ ]*/ /" $GUMMIBOOT_CFGS
|
|
||||||
# add the root= and other standard boot options
|
|
||||||
sed -i "s@options *@options root=PARTUUID=$rootuuid rw $rootwait quiet @" $GUMMIBOOT_CFGS
|
|
||||||
# if RMC feature presents, append global kernel command line fragment when it exists.
|
|
||||||
if [ -f "${RMC_DB}" ] && [ -f "${RMC_CMD}" ]; then
|
|
||||||
if ${RMC_CMD} -B KBOOTPARAM -d "${RMC_DB}" -o /tmp/kbootparam; then
|
|
||||||
sed -i "/^[ \t]*options/ s/$/ $(cat /tmp/kbootparam)/" $GUMMIBOOT_CFGS
|
|
||||||
rm /tmp/kbootparam
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp /run/media/$1/vmlinuz /boot
|
|
||||||
|
|
||||||
umount /src_root
|
|
||||||
umount /tgt_root
|
|
||||||
umount /boot
|
|
||||||
|
|
||||||
sync
|
|
||||||
|
|
||||||
echo "Remove your installation media, and press ENTER"
|
|
||||||
|
|
||||||
read enter
|
|
||||||
|
|
||||||
echo "Rebooting..."
|
|
||||||
reboot -f
|
|
|
@ -1,2 +0,0 @@
|
||||||
FILESEXTRAPATHS_prepend_intel-x86-common := "${THISDIR}/files:"
|
|
||||||
PACKAGE_ARCH_intel-x86-common = "${INTEL_COMMON_PACKAGE_ARCH}"
|
|
Loading…
Reference in New Issue
Block a user