diff --git a/.gitignore b/.gitignore
index aaa1502..2c9515a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-SOURCES/microcode_ctl-2.1-20180703.tar.xz
+SOURCES/microcode-20180807a.tgz
+SOURCES/microcode_ctl-2.1-14.tar.xz
diff --git a/.microcode_ctl.metadata b/.microcode_ctl.metadata
index 6888465..131e43b 100644
--- a/.microcode_ctl.metadata
+++ b/.microcode_ctl.metadata
@@ -1 +1,2 @@
-60aeb4e9b797c74941815ca4d5877507caee043c SOURCES/microcode_ctl-2.1-20180703.tar.xz
+20001bc89a46a40015d12f329910e4eb263d4e82 SOURCES/microcode-20180807a.tgz
+e2508bc2b2b359fb45be6fd5595612cffaca8024 SOURCES/microcode_ctl-2.1-14.tar.xz
diff --git a/SOURCES/06-4f-01_config b/SOURCES/06-4f-01_config
index c568ed5..f589fbf 100644
--- a/SOURCES/06-4f-01_config
+++ b/SOURCES/06-4f-01_config
@@ -11,3 +11,11 @@ kernel 2.6.32-573.58.1
 kernel 2.6.32-504.71.1
 kernel 2.6.32-431.90.1
 kernel 2.6.32-358.90.1
+kernel_early 4.10.0
+kernel_early 3.10.0-930
+kernel_early 3.10.0-862.14.1
+kernel_early 3.10.0-693.38.1
+kernel_early 3.10.0-514.57.1
+kernel_early 3.10.0-327.73.1
+mc_min_ver_late 0xb000019
+disable early late
diff --git a/SOURCES/06-4f-01_readme b/SOURCES/06-4f-01_readme
index afb4d2d..1eaa758 100644
--- a/SOURCES/06-4f-01_readme
+++ b/SOURCES/06-4f-01_readme
@@ -1,19 +1,52 @@
-The microcode for Broadwell-EP/EX (BDX-ML B/M/R0, family 6, model 79,
-stepping 1) processors requires a kernel with special commits present,
+The microcode for Intel Broadwell-EP/EX (BDX-ML B/M/R0, family 6, model 79,
+stepping 1) processors requires a kernel with specific commits present,
 otherwise it might result in unexpected system behaviour.  In order
 to handle this, /usr/libexec/microcode_ctl/update_ucode script creates
-necessary symlinks to make it available on kernels with the aforementioned
-patches present.
+necessary symlinks to make it available only on kernels with the aforementioned
+patches present.  The required patches are present in the following versions
+of the kernel package:
+	RHEL 7.6: kernel-3.10.0-894 or newer;
+	RHEL 7.5.z: kernel-3.10.0-862.6.1 or newer;
+	RHEL 7.4.z: kernel-3.10.0-693.35.1 or newer;
+	RHEL 7.3.z: kernel-3.10.0-514.52.1 or newer;
+	RHEL 7.2.z: kernel-3.10.0-327.70.1 or newer.
 
-If you want to avoid adding this ucode for a specific kernel, please create
-a disallow-06-4f-01 file inside /lib/firmware/<kernel_version> directory:
+Please use the version of the kernel with the aforementioned patches when
+running on Intel Broadwell EP/EX processors in order to have the microcode
+updated.
 
-    touch /lib/firmware/3.10.0-862.9.1/disallow-06-4f-01
+If you want to avoid late loading of this ucode for a specific kernel, please
+create "disallow-late-06-4f-01" file inside /lib/firmware/<kernel_version>
+directory and run /usr/libexec/microcode_ctl/update_ucode script:
 
-If you want to skip processing of this firmware for all kernels, please create
-a disallow-06-4f-01 file inside /etc/microcode_ctl/ucode_with_caveats directory:
+    touch /lib/firmware/3.10.0-862.9.1/disallow-late-06-4f-01
+    /usr/libexec/microcode_ctl/update_ucode
 
-    touch /etc/microcode_ctl/ucode_with_caveats/disallow-06-4f-01
+If you want to avoid late loading of this microcode for all kernels, please
+create "disallow-late-06-4f-01" file inside /etc/microcode_ctl/ucode_with
+caveats directory and run /usr/libexec/microcode_ctl/update_ucode script:
+
+    mkdir -p /etc/microcode_ctl/ucode_with_caveats
+    touch /etc/microcode_ctl/ucode_with_caveats/disallow-late-06-4f-01
+    /usr/libexec/microcode_ctl/update_ucode
+
+If you want to enforce addition of this microcode to the firmware directory
+for a specific kernel, please create "force-late-06-4f-01" file inside
+/lib/firmware/<kernel_version> directory and run
+dracut -f --kver "<kernel_version>":
+
+    touch /lib/firmware/3.10.0-862.9.1/force-early-06-4f-01
+    dracut -f --kver 3.10.0-862.9.1
+
+If you want to enforce addition of this microcode for all kernels, add a line
+"06-4f-01" to the file /etc/microcode_ctl/force-early-microcode and run
+dracut -f --regenerate-all:
+
+    echo 06-4f-01 >> /etc/microcode_ctl/force-early-microcode
+    dracut -f --regenerate-all
 
 If you want avoid removal of the ucode file during cleanup, please remove the
-corresponding readme file.
+corresponding readme file (copy of this file in /lib/firmware/<kernel_version>).
+
+
+See /usr/share/doc/microcode_ctl/README.caveats for additional information.
diff --git a/SOURCES/README.caveats b/SOURCES/README.caveats
new file mode 100644
index 0000000..a3fea12
--- /dev/null
+++ b/SOURCES/README.caveats
@@ -0,0 +1,398 @@
+The microcode_ctl package shipped with RHEL contains provisions for the issues
+with microcode loading on the old kernels.  While those provisions are expected
+to suit most users, several knobs are provided in order to provide ability
+to override the default behaviour.
+
+
+General behaviour
+=================
+In RHEL 7, there are currently two main handlers for microcode update:
+ * Early microcode update. It uses GenuineIntel.bin or AuthenticAMD.bin file
+   placed at the beginning of an initramfs image
+   (/boot/initramfs-KERNEL_VERSION.img) in order to update CPU microcode and
+   is performed very early during the boot process (if the relevant microcode
+   file is available).
+ * On-demand (late) microcode update. It can be triggered by writing "1" to
+   /sys/devices/system/cpu/microcode/reload file (provided my the "microcode"
+   module). It loads microcode from a file present in one of the following
+   directories:
+       /lib/firmware/updates/KERNEL_VERSION/
+       /lib/firmware/updates/
+       /lib/firmware/KERNEL_VERSION/
+       /lib/firmware/
+  (there is also an additional directory that can be configured via the
+  "fw_path_para" module option of the "firmware_class" module; as this module
+  is built-in in RHEL kernel, a boot parameter "firmware_class.fw_path_para"
+  should be used for that purpose; this is out of the document's scope, however)
+
+The firmware for Intel CPUs is searched in "intel-ucode" subdirectory, and for
+AMD CPUs, a file under "amd-ucode" is searched.
+
+For Intel CPUs, the name of the specific microcode file the kernel tries to load
+has the format "FF-MM-SS", where "FF" is the family number, "MM" is the model
+number, and "SS" is the stepping. All those numbers are zero-filled to two digits
+and are written in hexadecimal (letters are in the lower case).  For AMD CPUs,
+the file name has the format "microcode_amd_famFFh.bin", where "FF" is the
+family number, written in hexadecimal, letters are in the lower case, not
+zero-filled.
+
+The early microcode is placed into initramfs image by the "dracut" script, which
+scans the aforementioned subdirectories of the configured list of firmware
+directories (by default it consists of two directories in RHEL 7,
+"/lib/firmware/updates" and "/lib/firmware").
+
+In RHEL 7, AMD microcode is shipped as a part of the linux-firmware package,
+and Intel microcode is shipped as a part of the microcode_ctl package.
+
+The microcode_ctl package currently includes the following:
+ * Intel microcode files, placed in /usr/share/microcode_ctl directory;
+ * A dracut configuration file, /usr/lib/dracut/dracut.conf.d/01-microcode.conf,
+   that enables inclusion of early microcode to the generated initramfs
+   in dracut;
+ * A dracut module, /usr/lib/dracut/modules.d/99microcode_ctl-fw_dir_override,
+   that controls which additional firmware directories will be added to dracut's
+   default configuration;
+ * A systemd service file, microcode.service, that triggers microcode reload
+   late during boot;
+ * A set of directories in /usr/share/microcode_ctl/ucode_with_caveats, that
+   contain configuration and related data for various caveats related
+   to microcode;
+ * A set of support scripts, placed in /usr/libexec/microcode_ctl:
+   * "check_caveats" is an utility script that performs checks of the target
+     kernel (and running CPU) in accordance with caveat configuration files
+     in ucode_with_caveats directory and reports whether it passes them or not;
+   * "reload_microcode" is a script that is called by microcode.service and
+     triggers microcode reloading (by writing "1" to
+     /sys/devices/system/cpu/microcode/reload) if the running kernel passes
+     check_caveats checks.
+   * "update_ucode" is a script that populates symlinks to microcode files
+     in /lib/firmware, so it can be picked up by relevant kernels for the late
+     microcode loading.
+
+Also, microcode_ctl RPM includes triggers that run update_ucode script on every
+installation or removal of a kernel RPM in order to provide microcode files
+for newly installed kernels and cleanup symlinks for the uninstalled ones.
+
+
+Caveat configuration
+--------------------
+There is a directory for each caveat under
+/usr/share/microcode_ctl/ucode_with_caveats, containing the following files:
+ * "config", a configuration file for the caveat;
+ * "readme", that contains description of the caveat;
+ * set of related associated microcode files.
+
+"config" file is a set of lines each containing option name and its value,
+separated by white space.  Currently, the following options are supported:
+ * "model" option, which has format "VENDOR_ID FF-MM-SS", that specifies
+   to which CPU model the caveat is applicable (check_caveats ignores caveats
+   with non-matching models if "-m" option is passed to it). Can be set
+   in the configuration file only once (the last provided value is used).
+ * "vendor" option specifies CPUs of which vendor (as provided
+   in the /proc/cpuinfo file) the caveat is applicable to (check_caveats
+   ignores caveats with non-matching models when it is invoked with "-m"
+   option). Can be set in the configuration file only once.
+ * "path" is a glob pattern that specifies set of microcode files associated
+   with the caveat as a relative path to the caveat directory. This option
+   is used for populating files in /lib/firmware by update_ucode script and
+   for matching microcode file when dracut is run in host-only mode
+   (as in that case it uses only the first directory in firmware directory list
+   to look for the microcode file applicable to the host CPU).  Can be set
+   in the configuration file multiple times.
+ * "kernel" is a minimal kernel version that supports proper handling
+   of the related microcode files during late microcode load.  It may be
+   provided in one of the following formats that affect the way it is compared
+   to the running kernel version:
+    * A.B.C (where A, B, and C are decimal numbers), "upstream version". In this
+      case, simple version comparison against the respective part of the running
+      kernel version is used, and the running kernel version should be greater
+      or equal than the version provided in the configuration option in order
+      for comparison to succeed (that is, the first part, major version number,
+      of the running kernel version should be greater than the value provided
+      in the configuration option, or those should be equal and the second part,
+      minor version number, should be greater than the minor version number
+      of the kernel version provided in the configuration option, or the first
+      two parts should be equal and the third part, patch level, should
+      be greater or equal the patch level of the version in the configuration
+      option).
+    * A.B.C-Y (where A, B, C, and Y are decimal numbers), "Y-stream version".
+      In this case, A.B.C part should be equal, and Y part of the running kernel
+      version should be greater or equal than the Y part of the configuration
+      option version in order to satisfy the comparison requirement.
+    * A.B.C-Y.Z1.Z2 (where A, B, C, Y, Z1, and Z2 are decimal numbers),
+      "Z-stream version". In this case, A.B.C-Y part should be equal and Z1.Z2
+      part of the running kernel should be greater or equal than the respective
+      part of the configuration option version (when compared as a version)
+      for comparison to succeed.
+   Kernel version check passed if at least one comparison of the running kernel
+   version against a kernel version provided in a configuration option
+   succeeded.  The "kernel" configuration option can be provided
+   in the configuration file multiple times.
+ * "kernel_early" is a minimal kernel version that supports proper handling
+   of the related microcode during early microcode load. The format of the
+   option and its semantics is similar to the "kernel" configuration options.
+   This option can be provided multiple times as well.
+ * "mc_min_ver_late" is the minimal version of the currently loaded microcode
+   on the CPU (as reported in /proc/cpuinfo) that supports late microcode
+   update.  Microcode update will be attempted only if the currently loaded
+   microcode version is greater or equal the microcode version provided
+   in the configuration option. Can be set in the configuration file only once.
+ * "disable" is a way to disable a specific caveat from inside its
+   configuration. Argument for the argument is a list of stages ("early",
+   "late") for which the caveat should be disable. The configuration option
+   can be provided multiple times in a configuration file.
+ * "blacklist" is a marker for a start of list of blacklisted model names,
+   one model name per line. The model name of the running CPU (as reported
+   in /proc/cpuinfo) is compared against the names in the provided list, and,
+   if there is a match, caveat check fails.
+
+
+check_caveats script
+--------------------
+"check_caveats" is an utility script (called by update_ucode, reload_microcode,
+dracut module) that performs checks of the target kernel (and running CPU)
+in accordance with caveat configuration files in directory
+"/usr/share/microcode_ctl/ucode_with_caveats", and returns information, whether
+the system passes the checks, or not.
+
+Usage:
+    check_caveats [-e] [-k TARGET_KVER] [-c CONFIG]* [-m] [-v]'
+
+Options:
+  -e - check for early microcode load possibility (instead of late microcode
+       load). "kernel_early" caveat configuration options are used for checking
+       instead of "kernel", and "mc_min_ver_late" is not checked.
+  -k - target kernel version to check against, $(uname -r) is used otherwise.
+  -c - caveat(s) to check, all caveat configurations found inside
+       $MC_CAVEATS_DATA_DIR are checked otherwise.
+  -m - ignore caveats that do not apply to the current CPU model.
+  -v - verbose output.
+
+Environment:
+  MC_CAVEATS_DATA_DIR - directory that contains caveats configurations
+  FW_DIR - directory containing firmware files (per-kernel configuration
+           overrides are checked there)
+  CFG_DIR - directory containing global caveats overrides.
+
+Output:
+  Script returns information about caveats check results. Output has a format
+  of "KEY VALUE1 VALUE2 ..." with KEY defining the semantics of the VALUEs.
+  Currently, the following data is issued:
+   - "cfgs" - list of caveats that have been processed (and not skipped
+      due to missing "config", "readme", or a disallow-* override described
+      below);
+   - "skip_cfgs" - list of caveats that have been skipped (due to missing
+     config/readme file, or because of overrides);
+   - "paths" - list of glob patterns matching files associated with caveats
+     that have been processed;
+   - "ok_cfgs" - list of caveat configurations that have all the checks passed
+     (or have enforced by one of force-* overrides described below);
+   - "ok_paths" - list of glob patterns associated with caveat files from
+     the "ok_cfgs" list;
+   - "fail_cfgs" - list of caveats that have one of the checks failed.
+   - "fail_paths" - list of glob patterns associated with caveats from the
+     "fail_cfgs" list.
+
+Return value:
+  - 0 in case caveats check has passed, 1 otherwise.
+  - In "-d" mode, 0 is always returned.
+
+Overrides:
+
+When check_caveats perform its checks, it also checks for presence of files
+in specific places, and, if they exist, check_caveats skips a caveat or ignores
+its checks; that mechanism allows overriding the information provided
+in configuration on local systems and affect the behaviour of the microcode
+update process.
+
+Current list of overrides (where $FW_DIR and $CFG_DIR are the environment
+options described earlier; $kver - the currently processed kernel version,
+$s is the requested stage ("early" or "late"), $cfg is the caveat directory
+name):
+    $FW_DIR/$kver/disallow-$s-$cfg - skip a caveat for the requested stage for
+                                     a specific kernel version..
+    $FW_DIR/$kver/force-$s-$cfg - apply a specific caveat file for a specific
+                                  kernel version for the requested stage without
+				  performing any checks.
+    $FW_DIR/$kver/disallow-$cfg - skip a caveat for any stage for a specific
+                                  kernel version.
+    $FW_DIR/$kver/force-$cfg - apply a specific caveat for any stage
+                               for a specific kernel version without checks.
+    $FW_DIR/$kver/disallow-$s - skip all caveats for a specific stage
+                                for a specific kernel version.
+    $CFG_DIR/disallow-$s-$cfg - skip a caveat for a specific stage for all
+                                kernel versions.
+    $FW_DIR/$kver/force-$s - apply all caveats for a specific stage
+                             for a specific kernel version without checks.
+    $CFG_DIR/force-$s-$cfg - apply a specific caveat for a specific stage for
+                             all kernel versions without checks.
+    $FW_DIR/$kver/disallow - skip all caveats for all stages for a specific
+                             kernel version.
+    $CFG_DIR/disallow-$cfg - skip a caveat for all stages for all kernel
+                             versions.
+    $FW_DIR/$kver/force - apply all caveats for all stages for a specific kernel
+                          version without checks.
+    $CFG_DIR/force-$cfg - apply a caveat for all stages for all kernel versions
+                          without checks.
+    $CFG_DIR/disallow-$s - skip all caveat for all kernel versions
+                           for a specific stage.
+    $CFG_DIR/force-$s - apply all caveats for all kernel versions for  specific
+                        stage without checks.
+    $CFG_DIR/disallow - skip all caveats for all stages for all kernel versions
+                        (disable everything).
+    $CFG_DIR/force - force all caveats for all stages for all kernel versions
+                     (enable everything).
+
+The "apply" action above means creating symlinks in /lib/firmware by
+update_ucode in case of the "late" stage and adding caveat directory to the list
+of firmware directories by dracut plugin in case of the "early" stage.
+
+The files are checked for existence until the first match, so more specific
+overrides can override more broad ones.
+
+Also, a caveat is ignored if it lacks either config or readme file.
+
+
+update_ucode script
+-------------------
+"update_ucode" populates symlinks to microcode files in accordance with caveats
+configuration.  It enables late microcode loading that is invoked by triggering
+/sys/devices/system/cpu/microcode/reload file.  Since caveats depend
+on the kernel version, symlinks are populated inside
+"/lib/firmware/KERNEL_VERSION" directory for each installed kernel.
+As a consequence, this script is triggered upon each kernel package installation
+and removal.
+
+The script has two parts: common and kernel-version-specific.
+
+During the common part, files are populated from
+/usr/share/microcode_ctl/intel-ucode in /lib/firmware/intel-ucode. There are
+several possibilities to affect the process:
+ * Presence of "/etc/microcode_ctl/intel-ucode-disallow" file leads to skipping
+   the common part of the script.
+ * The same for "/lib/firmware/intel-ucode-disallow".
+
+During the kernel-version-specific part, each caveat is checked against every
+kernel version, and those combinations, for which caveat check succeeds,
+gets the symlinks to the associated microcode files populated.
+ * Absence of "/lib/firmware/KERNEL_VERSION/readme-CAVEAT" prevents update_ucode
+   from removing symlinks related to the caveat for specific kernel version.
+ * Since the check is being done by check_caveats, all the overrides that
+   described there also stay.
+
+Usage:
+    update_ucode [--action {add|remove|refresh|list}] [--kernel KERNELVER]*
+                 [--verbose] [--dry-run] [--cleanup intel_ucode caveats_ucode]
+                 [--skip-common] [--skip-kernel-specific]
+
+Options:
+  --action - action to perform. Currently, the following actions are supported:
+              * "add" - create new symlinks.
+              * "remove" - remove old symlinks that are no longer needed.
+              * "refresh" - re-populate symlinks.
+              * "list" - list files under control of update_ucode.
+             By default, "refresh" action is executed.
+  --kernel - kernel version to process. By default, list of kernel versions
+             is formed based on contents of /lib/firmware and /lib/modules
+             directories.
+  --verbose - verbose output.
+  --dry-run - do not call commands, just print the invocation lines.
+  --cleanup - cleanup mode. Used by post-uninstall script during package
+              upgrades. Removes excess files in accordance to the contents
+              of the files provided in the arguments to the option.
+  --skip-common - do not process /lib/firmware directory.
+  --skip-kernel-specific - do not process /lib/firmware/KERNEL_VERSION
+                           directories.
+
+Return value:
+  0 on success, 1 on error.
+
+
+reload_microcode script
+-----------------------
+"reload_microcode" is a script that is called by microcode.service and
+triggers late microcode reloading (by writing "1" to
+/sys/devices/system/cpu/microcode/reload) if the running kernel passes
+check_caveats checks that applicable to the current CPU model.
+
+The script checks /proc/cpuinfo for the presence of "hypervisor" flag
+and avoids triggering microcode update if it is there.
+
+The script has no options and always returns 0.
+
+In addition to overrides that affect check_caveats, the presence of the
+"/etc/microcode_ctl/ignore-hypervisor-flag" flag provides an ability
+to skip "hypervisor" flag check.
+
+
+99microcode_ctl-fw_dir_override dracut module
+---------------------------------------------
+This dracut module injects directories with microcode files for caveats
+that pass "early" check_caveats check (with "-e" flag). In addition
+to check_caveats overrides, the following abilities to control module behaviour
+are present:
+ * Presence of one of the following files:
+   - /etc/microcode_ctl/ucode_with_caveats/skip-host-only-check
+   - /etc/microcode_ctl/ucode_with_caveats/skip-host-only-check-$cfg
+   - /lib/firmware/$kver/skip-host-only-check
+   - /lib/firmware/$kver/skip-host-only-check-$cfg
+   (where "$kver" is the kernel version in question and "$cfg" is the caveat
+   directory name) allows skipping matching of microcode file name when dracut's
+   Host-Only mode is enabled.
+
+When caveats_check succeeds, caveats directory (and not
+/lib/firmware/KERNEL_VERSION) is added to the list of firmware search
+directories.  It is done so in order to enable independent caveat enablement
+for the initramfs image.
+
+The module can be disabled by running dracut with
+"-o microcode_ctl-fw_dir_override" (for one-time exclusion) or by creating
+a file *.conf inside /usr/lib/dracut/dracut.conf.d that contains
+"omit_dracutmodules+=' microcode_ctl-fw_dir_override '" in order to disable
+it permanently.  See dracut(8), section "Omitting dracut Modules", and
+dracut.conf(5), variable "omit_dracutmodules" for additional information.
+
+
+Caveats
+=======
+
+Intel Broadwell-EP/EX ("BDX-ML B/M/R0") caveat
+----------------------------------------------
+The microcode for Intel Broadwell-EP/EX (BDX-ML B/M/R0, family 6, model 79,
+stepping 1) processors requires a kernel with specific commits present,
+otherwise it might result in unexpected system behaviour.
+
+Affected microcode: intel-ucode/06-4f-01.
+
+Mitigation: late microcode loading is disabled for the affected CPU model.
+
+Minimum versions of kernel RPM that contain the fix:
+ - RHEL 7.6:  3.10.0-894
+ - RHEL 7.5:  3.10.0-862.6.1
+ - RHEL 7.4:  3.10.0-693.35.1
+ - RHEL 7.3:  3.10.0-514.52.1
+ - RHEL 7.2:  3.10.0-327.70.1
+ - RHEL 6.10: 2.6.32-754.1.1
+ - RHEL 6.7:  2.6.32-573.58.1
+ - RHEL 6.6:  2.6.32-504.71.1
+ - RHEL 6.5:  2.6.32-431.90.1
+ - RHEL 6.4:  2.6.32-358.90.1
+
+
+Early microcode load inside a virtual machine
+---------------------------------------------
+RHEL 7 kernel supports early microcode load from cpio archive placed
+at the beginning of initramfs image.  However, when early microcode loading
+is attempted inside some virtualised environments, that may result
+in unexpected system behaviour.
+
+Affected microcode: all.
+
+Mitigation: early microcode loading is disabled for all CPU models.
+
+Minimum versions of kernel RPM that contain the fix:
+ - RHEL 7.6: 3.10.0-930
+ - RHEL 7.5: 3.10.0-862.14.1
+ - RHEL 7.4: 3.10.0-693.38.1
+ - RHEL 7.3: 3.10.0-514.57.1
+ - RHEL 7.2; 3.10.0-327.73.1
diff --git a/SOURCES/check_caveats b/SOURCES/check_caveats
index 04975c2..dd52742 100755
--- a/SOURCES/check_caveats
+++ b/SOURCES/check_caveats
@@ -6,10 +6,14 @@
 # SPDX-License-Identifier: CC0-1.0
 
 : ${MC_CAVEATS_DATA_DIR=/usr/share/microcode_ctl/ucode_with_caveats}
+: ${FW_DIR=/lib/firmware}
+: ${CFG_DIR=/etc/microcode_ctl/ucode_with_caveats}
 
 usage() {
-	echo 'Usage: check_caveats [-k TARGET_KVER] [-c CONFIG] [-m] [-v]'
+	echo 'Usage: check_caveats [-e] [-k TARGET_KVER] [-c CONFIG] [-m] [-v]'
 	echo
+	echo '   -e - check for early microcode load possibility (instead of'
+	echo '        late microcode load)'
 	echo '   -k - target version to check against, $(uname -r) is used'
 	echo '        otherwise'
 	echo '   -c - caveat config(s) to check, all configs are checked'
@@ -40,22 +44,22 @@ check_kver()
 	# IFS=.- read -r t_major t_minor t_patch t_y t_z1 t_z2 t_rest <<<"$1"
 	# "cannot create temp file for here-document: Read-only file system"
 	# that's why we can't have nice things.
-	t_major=${1%%[.-]*}
+	t_major=${1%%.*}
 	t_rest=${1#${t_major}}
-	t_rest=${t_rest#[.-]}
-	t_minor=${t_rest%%[.-]*}
+	t_rest=${t_rest#.}
+	t_minor=${t_rest%%.*}
 	t_rest=${t_rest#${t_minor}}
-	t_rest=${t_rest#[.-]}
-	t_patch=${t_rest%%[.-]*}
+	t_rest=${t_rest#.}
+	t_patch=${t_rest%%-*}
 	t_rest=${t_rest#${t_patch}}
-	t_rest=${t_rest#[.-]}
-	t_y=${t_rest%%[.-]*}
+	t_rest=${t_rest#-}
+	t_y=${t_rest%%.*}
 	t_rest=${t_rest#${t_y}}
-	t_rest=${t_rest#[.-]}
-	t_z1=${t_rest%%[.-]*}
+	t_rest=${t_rest#.}
+	t_z1=${t_rest%%.*}
 	t_rest=${t_rest#${t_z1}}
-	t_rest=${t_rest#[.-]}
-	t_z2=${t_rest%%[.-]*}
+	t_rest=${t_rest#.}
+	t_z2=${t_rest%%.*}
 
 	# minor/major/patch/y should be numeric
 	[ -n "${t_major##*[!0-9]*}" ] || return 1
@@ -70,22 +74,22 @@ check_kver()
 		cmp_type=upstream
 
 		shift
-		m_major=${1%%[.-]*}
+		m_major=${1%%.*}
 		m_rest=${1#${m_major}}
-		m_rest=${m_rest#[.-]}
-		m_minor=${m_rest%%[.-]*}
+		m_rest=${m_rest#.}
+		m_minor=${m_rest%%.*}
 		m_rest=${m_rest#${m_minor}}
-		m_rest=${m_rest#[.-]}
-		m_patch=${m_rest%%[.-]*}
+		m_rest=${m_rest#.}
+		m_patch=${m_rest%%-*}
 		m_rest=${m_rest#${m_patch}}
-		m_rest=${m_rest#[.-]}
-		m_y=${m_rest%%[.-]*}
+		m_rest=${m_rest#-}
+		m_y=${m_rest%%.*}
 		m_rest=${m_rest#${m_y}}
-		m_rest=${m_rest#[.-]}
-		m_z1=${m_rest%%[.-]*}
+		m_rest=${m_rest#.}
+		m_z1=${m_rest%%.*}
 		m_rest=${m_rest#${m_z1}}
-		m_rest=${m_rest#[.-]}
-		m_z2=${m_rest%%[.-]*}
+		m_rest=${m_rest#.}
+		m_z2=${m_rest%%.*}
 
 		# minor/major/patch should be numeric
 		[ -n "${m_major##*[!0-9]*}" ] || continue
@@ -146,6 +150,24 @@ get_model_name()
 	/bin/sed -rn '1,/^$/s/^model name[[:space:]]*: (.*)$/\1/p' /proc/cpuinfo
 }
 
+get_vendor_id()
+{
+	/bin/sed -rn '1,/^$/s/^vendor_id[[:space:]]*: (.*)$/\1/p' /proc/cpuinfo
+}
+
+get_mc_ver()
+{
+	/bin/sed -rn '1,/^$/s/^microcode[[:space:]]*: (.*)$/\1/p' /proc/cpuinfo
+}
+
+fail()
+{
+	ret=1
+
+	fail_cfgs="$fail_cfgs $cfg"
+	fail_paths="$fail_paths $cfg_path"
+}
+
 #check_kver "$@"
 #get_model_name
 
@@ -153,9 +175,15 @@ match_model=0
 configs=
 kver=$(/bin/uname -r)
 verbose=0
+early_check=0
+
+ret=0
 
-while getopts "k:c:mv" opt; do
+while getopts "ek:c:mv" opt; do
 	case "${opt}" in
+	e)
+		early_check=1
+		;;
 	k)
 		kver="$OPTARG"
 		;;
@@ -179,30 +207,74 @@ done
 
 cpu_model=$(get_model_string)
 cpu_model_name=$(get_model_name)
+cpu_vendor=$(get_vendor_id)
+
+ret_paths=""
+ok_paths=""
+fail_paths=""
+
+ret_cfgs=""
+ok_cfgs=""
+fail_cfgs=""
+
+skip_cfgs=""
+
+if [ 1 -eq "$early_check" ]; then
+	stage="early"
+else
+	stage="late"
+fi
+
 
 for cfg in $(echo "${configs}"); do
 	dir="$MC_CAVEATS_DATA_DIR/$cfg"
+
+	# We add cfg to the skip list first and then, if we do not skip it,
+	# we remove the configuration from the list.
+	skip_cfgs="$skip_cfgs $cfg"
+
+	[ -r "${dir}/readme" ] || {
+		debug "File 'readme' in ${dir} is not found, skipping"
+		continue
+	}
+
 	[ -r "${dir}/config" ] || {
 		debug "File 'config' in ${dir} is not found, skipping"
 		continue
 	}
 
 	cfg_model=
+	cfg_vendor=
 	cfg_path=
 	cfg_kvers=
+	cfg_kvers_early=
 	cfg_blacklist=
+	cfg_mc_min_ver_late=
+	cfg_disable=
 
 	while read -r key value; do
 		case "$key" in
 		model)
 			cfg_model="$value"
 			;;
+		vendor)
+			cfg_vendor="$value"
+			;;
 		path)
 			cfg_path="$cfg_path $value"
 			;;
 		kernel)
 			cfg_kvers="$cfg_kvers $value"
 			;;
+		kernel_early)
+			cfg_kvers_early="$cfg_kvers_early $value"
+			;;
+		mc_min_ver_late)
+			cfg_mc_min_ver_late="$value"
+			;;
+		disable)
+			cfg_disable="$cfg_disable $value "
+			;;
 		blacklist)
 			cfg_blacklist=1
 			break
@@ -217,35 +289,161 @@ for cfg in $(echo "${configs}"); do
 	debug "${cfg}: model '$cfg_model', path '$cfg_path', kvers '$cfg_kvers'"
 	debug "${cfg}: blacklist '$cfg_blacklist'"
 
-	if [ -n "$cfg_model" ]; then
-		[ 0 -eq "$match_model" ] || {
-			[ "x$cpu_model" = "x$cfg_model" ] || {
-				debug "Current CPU model '$cpu_model' doesn't" \
-				      "match config CPU model '$cfg_model'," \
-				      "skipping"
-				continue
-			}
+	# Check for override files in the following order:
+	#  - disallow early/late specific caveat for specific kernel
+	#  - force early/late specific caveat for specific kernel
+	#  - disallow specific caveat for specific kernel
+	#  - force specific caveat for specific kernel
+	#
+	#  - disallow early/late specific caveat for any kernel
+	#  - disallow early/late any caveat for specific kernel
+	#  - force early/late specific caveat for any kernel
+	#  - force early/late any caveat for specific kernel
+	#  - disallow specific caveat for any kernel
+	#  - disallow any caveat for specific kernel
+	#  - force specific caveat for any kernel
+	#  - force any caveat for specific kernel
+	#
+	#  - disallow early/late everything
+	#  - force early/late everyhting
+	#  - disallow everything
+	#  - force everyhting
+	ignore_cfg=0
+	force_cfg=0
+	override_file=""
+	overrides="
+	0:$FW_DIR/$kver/disallow-$stage-$cfg
+	1:$FW_DIR/$kver/force-$stage-$cfg
+	0:$FW_DIR/$kver/disallow-$cfg
+	1:$FW_DIR/$kver/force-$cfg
+	0:$FW_DIR/$kver/disallow-$stage
+	0:$CFG_DIR/disallow-$stage-$cfg
+	1:$FW_DIR/$kver/force-$stage
+	1:$CFG_DIR/force-$stage-$cfg
+	0:$FW_DIR/$kver/disallow
+	0:$CFG_DIR/disallow-$cfg
+	1:$FW_DIR/$kver/force
+	1:$CFG_DIR/force-$cfg
+	0:$CFG_DIR/disallow-$stage
+	1:$CFG_DIR/force-$stage
+	0:$CFG_DIR/disallow
+	1:$CFG_DIR/force"
+	for o in $(echo "$overrides"); do
+		o_force=${o%%:*}
+		override_file=${o#$o_force:}
+
+		[ -e "$override_file" ] || continue
+
+		if [ 0 -eq "$o_force" ]; then
+			ignore_cfg=1
+		else
+			force_cfg=1
+		fi
+
+		break
+	done
+
+	[ 0 -eq "$ignore_cfg" ] || {
+		debug "Configuration \"$cfg\" is ignored due to presence of" \
+		      "\"$override_file\"."
+		continue
+	}
+
+	# Check model if model filter is enabled
+	if [ 1 -eq "$match_model" -a  -n "$cfg_model" ]; then
+		[ "x$cpu_model" = "x$cfg_model" ] || {
+			debug "Current CPU model '$cpu_model' doesn't" \
+			      "match configuration CPU model '$cfg_model'," \
+			      "skipping"
+			continue
+		}
+	fi
+
+	# Check vendor if model filter is enabled
+	if [ 1 -eq "$match_model" -a  -n "$cfg_vendor" ]; then
+		[ "x$cpu_vendor" = "x$cfg_vendor" ] || {
+			debug "Current CPU vendor '$cpu_vendor' doesn't" \
+			      "match configuration CPU vendor '$cfg_vendor'," \
+			      "skipping"
+			continue
 		}
 	fi
 
-	if [ -n "$cfg_kvers" ]; then
+	# Check configuration files
+
+	ret_cfgs="$ret_cfgs $cfg"
+	ret_paths="$ret_paths $cfg_path"
+	skip_cfgs="${skip_cfgs% $cfg}"
+
+	[ 0 -eq "$force_cfg" ] || {
+		debug "Checks for configuration \"$cfg\" are ignored due to" \
+		      "presence of \"$override_file\"."
+
+		ok_cfgs="$ok_cfgs $cfg"
+		ok_paths="$ok_paths $cfg_path"
+
+		continue
+	}
+
+	[ "x${cfg_disable%%* $stage *}" = "x$cfg_disable" ] || {
+		debug "${cfg}: caveat is disabled in configuration"
+		fail
+		continue
+	}
+
+	# Check late load kernel version
+	if [ 1 -ne "$early_check" -a -n "$cfg_kvers" ]; then
 		check_kver "$kver" $cfg_kvers || {
-			debug "${cfg}: kernel version check for '$kver'" \
-			      "against '$cfg_kvers' failed"
-			exit 1
+			debug "${cfg}: late load kernel version check for" \
+			      " '$kver' against '$cfg_kvers' failed"
+			fail
+			continue
 		}
 	fi
 
+	# Check early load kernel version
+	if [ 0 -ne "$early_check" -a -n "$cfg_kvers_early" ]; then
+		check_kver "$kver" $cfg_kvers_early || {
+			debug "${cfg}: early load kernel version check for" \
+			      "'$kver' against '$cfg_kvers_early' failed"
+			fail
+			continue
+		}
+	fi
+
+	# Check model blacklist
 	if [ -n "$cfg_blacklist" ]; then
 		echo "$cfg_blacklist" | /bin/grep -vqFx "${cpu_model_name}" || {
 			debug "${cfg}: model '${cpu_model_name}' is blacklisted"
-			exit 1
+			fail
+			continue
+		}
+	fi
+
+	# Check current microcode version for the late update
+	if [ -n "$cfg_mc_min_ver_late" -a 1 -ne "$early_check" -a \
+	   "x$cpu_model" = "x$cfg_model" ]; then
+		cpu_mc_ver="$(get_mc_ver)"
+
+		[ 1 -eq $((cpu_mc_ver >= cfg_mc_min_ver_late)) ] || {
+			debug "${cfg}: CPU microcode version $cpu_mc_ver" \
+			      "failed check (should be at least" \
+			      "${cfg_mc_min_ver_late})"
+			fail
+			continue
 		}
 	fi
 
-	#printf "%s " "$cfg"
-	#[ 0 -eq "$match_model" ] || printf "%s " "$cpu_model"
-	echo $cfg_path
+	ok_cfgs="$ok_cfgs $cfg"
+	ok_paths="$ok_paths $cfg_path"
 done
 
-exit 0
+echo "cfgs$ret_cfgs"
+echo "skip_cfgs$skip_cfgs"
+echo "paths$ret_paths"
+echo "ok_cfgs$ok_cfgs"
+echo "ok_paths$ok_paths"
+echo "fail_cfgs$fail_cfgs"
+echo "fail_paths$fail_paths"
+
+exit $ret
diff --git a/SOURCES/dracut_99microcode_ctl-fw_dir_override_module_init.sh b/SOURCES/dracut_99microcode_ctl-fw_dir_override_module_init.sh
index 200548c..7d88111 100755
--- a/SOURCES/dracut_99microcode_ctl-fw_dir_override_module_init.sh
+++ b/SOURCES/dracut_99microcode_ctl-fw_dir_override_module_init.sh
@@ -1,9 +1,6 @@
 #!/bin/bash
 
-# Hack in kernel-specific firmware directory so it can be processed along with
-# the dracut default ones.  Note that upstream dracut currently has defaults
-# that include kernel-version-specific directories (dracut commit
-# 041-100-gb52cfbea).
+# Hack in additional firmware directories for supported caveats.
 #
 # SPDX-License-Identifier: CC0-1.0
 
@@ -11,69 +8,146 @@ check() {
 	return 0
 }
 
-DATA_DIR=/usr/share/microcode_ctl/ucode_with_caveats
-check_caveats=/usr/libexec/microcode_ctl/check_caveats
-
 install() {
+	local FW_DIR=/lib/firmware
+	local DATA_DIR=/usr/share/microcode_ctl/ucode_with_caveats
+	local CFG_DIR="/etc/microcode_ctl/ucode_with_caveats"
+	local check_caveats=/usr/libexec/microcode_ctl/check_caveats
+
+	local verbose_opt
+	local cc_out
+	local path
+	local ignored
+	local do_skip_host_only
+	local p
+
 	verbose_opt=
 	[ 4 -gt "$stdloglvl" ] || verbose_opt="-v"
 
 	# HACK: we override external fw_dir variable in order to get
 	#       an additional ucode based on the kernel version.
-	dinfo "  microcode_ctl module: hacking fw_dir"
+	dinfo "  microcode_ctl module: mangling fw_dir"
 
 	[ -z "$fw_dir_l" ] || {
-		dinfo "    microcode_ctl module: avoid touching fw_dir as" \
+		dinfo "    microcode_ctl: avoid touching fw_dir as" \
 		      "it has been changed (fw_dir_l is '$fw_dir_l')"
 
 		return 0
 	}
 
-	ucode=$(get_ucode_file)
+	# Reset fw_dir to avoid inclusion of kernel-version-specific directories
+	# populated with microcode for the late load
+	[ "x$fw_dir" != \
+	  "x/lib/firmware/updates /lib/firmware /lib/firmware/$kernel" ] || {
+		fw_dir="/lib/firmware/updates /lib/firmware"
+		dinfo "    microcode_ctl: reset fw_dir to \"${fw_dir}\""
+	}
 
-	for i in $(ls "$DATA_DIR"); do
+	while read -d "/" -r i; do
 		dinfo "    microcode_ctl: processing data directory " \
 		      "\"$DATA_DIR/$i\"..."
-		[ -e "$DATA_DIR/$i/readme" ] || {
-			dinfo "      microcode_ctl: skipping \"$i\": no readme"
-			continue
-		}
-		[ -e "$DATA_DIR/$i/config" ] || {
-			dinfo "    microcode_ctl: skipping \"$i\": no config"
+
+		if ! cc_out=$($check_caveats -e -k "$kernel" -c "$i" $verbose_opt)
+		then
+			dinfo "    microcode_ctl: kernel version \"$kernel\"" \
+			      "failed early load check for \"$i\", skipping"
 			continue
-		}
-		[ ! -e "/etc/microcode_ctl/ucode_with_caveats/disallow-$i" ] || {
-			dinfo "    microcode_ctl: skipping \"$i\":" \
-			      "\"/etc/microcode_ctl/ucode_with_caveats/disallow-$i\"" \
-			      "present"
+		fi
+
+		path=$(printf "%s" "$cc_out" | sed -n 's/^paths //p')
+		[ -n "$path" ] || {
+			ignored=$(printf "%s" "$cc_out" | \
+					sed -n 's/^skip_cfgs //p')
+
+			if [ -n "$ignored" ]; then
+				dinfo "    microcode_ctl: configuration" \
+				      "\"$i\" is ignored"
+			else
+				dinfo "    microcode_ctl: no microcode paths" \
+				      "are associated with \"$i\", skipping"
+			fi
+
 			continue
 		}
-		path=$($check_caveats -k "$kernel" -c "$i")
-                fname=$(basename "$path")
 
 		if [ "x" != "x$hostonly" ]; then
-			[ "x$ucode" = "x$fname" ] || {
-				dinfo "    microcode_ctl: Host-Only mode" \
-                                      "is enabled and ucode name does not" \
-                                      "match the expected one" \
-                                      "(\"$ucode\" != \"$fname\")"
+			do_skip_host_only=0
+
+			local sho_overrides="
+				$CFG_DIR/skip-host-only-check
+				$CFG_DIR/skip-host-only-check-$i
+				$FW_DIR/$kernel/skip-host-only-check
+				$FW_DIR/$kernel/skip-host-only-check-$i"
+
+			for p in $(echo "$sho_overrides"); do
+				[ -e "$p" ] || continue
+
+				do_skip_host_only=1
+				dinfo "    microcode_ctl: $i; skipping" \
+				      "Host-Only check, since \"$p\" exists."
+				break
+			done
+		else
+			do_skip_host_only=1
+		fi
+
+		if [ 0 -eq "$do_skip_host_only" ]; then
+			local hostonly_passed=0
+			local ucode
+			local uvendor
+			local ucode_dir=""
+
+			ucode=$(get_ucode_file)
+			uvendor=$(get_cpu_vendor)
+
+			case "$uvendor" in
+			Intel)
+				ucode_dir="intel-ucode"
+				;;
+			AMD)
+				ucode_dir="and-ucode"
+				;;
+			*)
+				dinfo "    microcode_ctl: unknown CPU" \
+				      "vendor: \"$uvendor\", bailing out of" \
+				      "Host-Only check"
+				continue
+				;;
+			esac
+
+			# $path is a list of globs, so it needs special care
+			for p in $(printf "%s" "$path"); do
+				find "$DATA_DIR/$i" -path "$DATA_DIR/$i/$p" \
+					-print0 \
+				    | grep -zFxq \
+					"$DATA_DIR/$i/$ucode_dir/$ucode" \
+				    || continue
+
+				dinfo "    microcode_ctl: $i: Host-Only" \
+				      "mode is enabled and" \
+				      "\"$ucode_dir/$ucode\" matches \"$p\""
+
+				hostonly_passed=1
+				break
+			done
+
+			[ 1 -eq "$hostonly_passed" ] || {
+				dinfo "    microcode_ctl: $i: Host-Only mode" \
+				      "is enabled and ucode name does not" \
+				      "match the expected one, skipping" \
+				      "caveat (\"$ucode\" not in \"$path\")"
 				continue
 			}
 		fi
 
-		dinfo "    microcode_ctl: processing file \"$path\""
-		if $check_caveats -k "$kernel" -c "$i" $verbose_opt > /dev/null
-		then
-			dinfo "      microcode_ctl: caveats check for kernel" \
-			      "version \"$kernel\" passed, adding" \
-			      "\"/lib/firmware/$kernel\" to fw_dir variable"
-			fw_dir="/lib/firmware/$kernel $fw_dir"
-			break
-		else
-			dinfo "      microcode_ctl: kernel version \"$kernel\"" \
-			      "failed caveats check, skipping"
-			continue
-		fi
-	done
+		dinfo "      microcode_ctl: $i: caveats check for kernel" \
+		      "version \"$kernel\" passed, adding" \
+		      "\"$DATA_DIR/$i\" to fw_dir variable"
+		fw_dir="$DATA_DIR/$i $fw_dir"
+	done <<-EOF
+	$(find "$DATA_DIR" -maxdepth 1 -mindepth 1 -type d -printf "%f/")
+	EOF
+
+	dinfo "    microcode_ctl: final fw_dir: \"${fw_dir}\""
 }
 
diff --git a/SOURCES/intel-microcode2ucode.8.in b/SOURCES/intel-microcode2ucode.8.in
new file mode 100644
index 0000000..829ec9f
--- /dev/null
+++ b/SOURCES/intel-microcode2ucode.8.in
@@ -0,0 +1,90 @@
+.\" intel-microcode2ucode stub man page
+.\"
+.\" SPDX-License-Identifier: CC0-1.0
+.\"
+.TH INTEL-MICROCODE2UCODE 8 "@DATE@" "MICROCODE_CTL @VERSION@"
+.\"
+.SH NAME
+intel\-microcode2ucode \- convert Intel microcode.dat file into ucode files
+.\"
+.SH SYNOPSIS
+.SY intel\-microcode2ucode
+.RI [ MICROCODE_FILE ]
+.YS
+.\"
+.SH DESCRIPTION
+.B intel\-microcode2ucode
+parses Intel microcode combined text data file (which usually has name
+.BR microcode.dat )
+and splits it into individual binary microcode files that can be loaded by the
+Linux kernel.
+.LP
+Generated microcode files are placed into
+.B intel-ucode
+directory, which is created in the current working directory, and have file name
+format of
+.IR FF - MM - SS ,
+where
+.I FF
+is the CPU family number,
+.I MM
+is the model number, and
+.I SS
+is stepping.
+All three values are zero-filled to two digits and are hexadecimal
+(letters are in the lower case).
+.LP
+This tool is mostly of historic interest, as Intel ships separate microcode
+files now.
+.\"
+.SH OPTIONS
+.\"
+.TP
+.I MICROCODE_FILE
+Path to the
+.B microcode.dat
+file.
+If no path has been provided, the default path
+.B /lib/firmware/microcode.dat
+is used.
+If
+.B -
+(single dash) is provided as an argument, data is read from the standard input.
+.\"
+.SH EXIT STATUS
+.TP
+.B 0
+Success.
+.TP
+.B 1
+Error occurred:
+temporary buffer cannot be allocated,
+input microcode file cannot be opened,
+microcode version and/or format are unknown,
+cannot open output file,
+cannot write to the output file.
+.\"
+.SH REPORTING BUGS
+Problems with
+.B intel-microcode2ucode
+should be reported to
+.UR https://bugzilla.redhat.com/
+Red Hat Bugzilla
+.UE
+.\"
+.SH AUTHORS
+.B intel-microcode2ucode
+was written by
+Kay Sievers <kay.sievers@vrfy.org> and
+Anton Arapov <anton@redhat.com>.
+This manpage was written for Red Hat Enterprise Linux and may be
+used, modified, and/or distributed freely by anyone.
+.\"
+.SH "SEE ALSO"
+.UR https://gitlab.com\:/iucode-tool\:/iucode-tool
+iucode-tool, a tool for manipulating Intel microcode files
+.UE ,
+.LP
+.UR @MICROCODE_URL@
+Intel microcode
+.UE
diff --git a/SOURCES/intel_config b/SOURCES/intel_config
new file mode 100644
index 0000000..d37878d
--- /dev/null
+++ b/SOURCES/intel_config
@@ -0,0 +1,8 @@
+path intel-ucode/*
+vendor_id GenuineIntel
+kernel_early 4.10.0
+kernel_early 3.10.0-930
+kernel_early 3.10.0-862.14.1
+kernel_early 3.10.0-693.38.1
+kernel_early 3.10.0-514.57.1
+kernel_early 3.10.0-327.73.1
diff --git a/SOURCES/intel_readme b/SOURCES/intel_readme
new file mode 100644
index 0000000..6250d1e
--- /dev/null
+++ b/SOURCES/intel_readme
@@ -0,0 +1,53 @@
+Older RHEL 7 kernels try to early load microcode even inside virtual
+machine, which may lead to panic on some hypervisors.  In order to circumvent
+that, microcode is installed into a kernel-version-specific directory (which
+is not scanned by the dracut script, that constructs early microcode binary
+in initramfs, by default), and path to microcode files provided only in case
+initramfs is generated for the kernel version that properly handles early
+microcode inside a virtual machine (i.e. do not attempts yo load it).
+The versions of the kernel package that properly handle early microcode load
+inside a virtual machine are as follows:
+	RHEL 7.6: kernel-3.10.0-930 or newer;
+	RHEL 7.5: kernel-3.10.0-862.14.1 or newer;
+	RHEL 7.4: kernel-3.10.0-693.38.1 or newer;
+	RHEL 7.3: kernel-3.10.0-514.57.1 or newer.
+	RHEL 7.2: kernel-3.10.0-327.73.1 or newer.
+
+If you want to avoid adding this ucode for a specific kernel, please create
+"disallow-early-intel" file inside /lib/firmware/<kernel_version> directory
+and run dracut -f:
+
+    touch /lib/firmware/3.10.0-862.9.1/disallow-intel
+    /usr/libexec/microcode_ctl/update_ucode
+    dracut -f --kver 3.10.0-862.9.1
+
+If you want to skip processing of this microcode for all kernels, please create
+"disallow-early-intel" file inside the "/etc/microcode_ctl/ucode_with_caveats"
+directory and run dracut -f --regenerate-all:
+
+    mkdir -p /etc/microcode_ctl/ucode_with_caveats
+    touch /etc/microcode_ctl/ucode_with_caveats/disallow-intel
+    dracut -f --kver 3.10.0-862.9.1
+
+If you want to enforce addition of this microcode to initramfs for a specific
+kernel, please create "force-early-intel" file inside
+/lib/firmware/<kernel_version> directory and run
+dracut -f --kver "<kernel_version>":
+
+    modir -p/lib/firmware/3.10.0-862.9.1/
+    touch /lib/firmware/3.10.0-862.9.1/force-early-intel
+    dracut -f --kver 3.10.0-862.9.1
+
+If you want to enforce addition of this microcode for all kernels, please
+create "force-early-intel" file inside /etc/microcode_ctl/ucode_with_caveats
+directory and run dracut -f --kver "<kernel_version>":
+
+    mkdir -p /etc/microcode_ctl/ucode_with_caveats
+    touch /etc/microcode_ctl/ucode_with_caveats/force-early-intel
+    dracut -f --regenerate-all
+
+In order to override late load behaviour, the "early" part of file names should
+be replaced with "late".
+
+
+See /usr/share/doc/microcode_ctl/README.caveats for additional information.
diff --git a/SOURCES/microcode_ctl-do-not-install-intel-ucode.patch b/SOURCES/microcode_ctl-do-not-install-intel-ucode.patch
new file mode 100644
index 0000000..5e5603c
--- /dev/null
+++ b/SOURCES/microcode_ctl-do-not-install-intel-ucode.patch
@@ -0,0 +1,20 @@
+Index: microcode_ctl-2.1-14/Makefile
+===================================================================
+--- microcode_ctl-2.1-14.orig/Makefile	2018-08-29 04:23:03.368699515 +0200
++++ microcode_ctl-2.1-14/Makefile	2018-08-29 04:24:00.498140839 +0200
+@@ -29,14 +29,13 @@
+ 	tar -xf $(MICROCODE_INTEL)
+ 
+ clean:
+-	rm -rf $(PROGRAM) intel-ucode
++	rm -rf $(PROGRAM)
+ 
+ install:
+ 	$(INS) -d $(DESTDIR)$(INSDIR) $(DESTDIR)$(DOCDIR) \
+ 		$(DESTDIR)$(MICDIRINTEL)
+ 	$(INS) -m 755 $(PROGRAM) $(DESTDIR)$(INSDIR)
+ 	$(INS) -m 644 README $(DESTDIR)$(DOCDIR)
+-	$(INS) -m 644 intel-ucode/* $(DESTDIR)$(MICDIRINTEL)
+ 
+ uninstall:
+ 	rm -rf $(DESTDIR)$(INSDIR)/$(PROGRAM) \
diff --git a/SOURCES/microcode_ctl-do-not-pipe-to-intel_microcode2ucode.patch b/SOURCES/microcode_ctl-do-not-pipe-to-intel_microcode2ucode.patch
new file mode 100644
index 0000000..fc6934b
--- /dev/null
+++ b/SOURCES/microcode_ctl-do-not-pipe-to-intel_microcode2ucode.patch
@@ -0,0 +1,13 @@
+Index: microcode_ctl-2.1-14/Makefile
+===================================================================
+--- microcode_ctl-2.1-14.orig/Makefile	2017-11-22 08:19:31.000000000 +0100
++++ microcode_ctl-2.1-14/Makefile	2018-08-09 07:10:34.562202626 +0200
+@@ -26,7 +26,7 @@
+ 
+ microcode_ctl: intel-microcode2ucode.c
+ 	$(CC) $(CFLAGS) -o $(PROGRAM) intel-microcode2ucode.c
+-	tar -xOf $(MICROCODE_INTEL) | ./intel-microcode2ucode - >/dev/null
++	tar -xf $(MICROCODE_INTEL)
+ 
+ clean:
+ 	rm -rf $(PROGRAM) intel-ucode
diff --git a/SOURCES/microcode_ctl-intel-microcode2ucode-buf-handling.patch b/SOURCES/microcode_ctl-intel-microcode2ucode-buf-handling.patch
new file mode 100644
index 0000000..9a014a8
--- /dev/null
+++ b/SOURCES/microcode_ctl-intel-microcode2ucode-buf-handling.patch
@@ -0,0 +1,95 @@
+Fix most obvious intel-microcode2ucode buffer overruns.
+Index: microcode_ctl-2.1-19/intel-microcode2ucode.c
+===================================================================
+--- microcode_ctl-2.1-19.orig/intel-microcode2ucode.c	2018-08-20 04:32:26.803450076 +0200
++++ microcode_ctl-2.1-19/intel-microcode2ucode.c	2018-08-20 04:33:49.324661025 +0200
+@@ -47,16 +47,25 @@
+ 	char c[0];
+ };
+ 
++#define MAX_MICROCODE 4000000
++
+ int main(int argc, char *argv[])
+ {
+ 	char *filename = "/lib/firmware/microcode.dat";
+ 	FILE *input, *f;
+ 	char line[LINE_MAX];
+-	char buf[4000000];
++	char *buf = NULL;
+ 	union mcbuf *mc;
+ 	size_t bufsize, count, start;
+ 	int rc = EXIT_SUCCESS;
+ 
++	buf = malloc(MAX_MICROCODE);
++	if (!buf) {
++		printf("can't allocate buffer\n");
++		rc = EXIT_FAILURE;
++		goto out;
++	}
++
+ 	if (argv[1] != NULL)
+ 		filename = argv[1];
+ 
+@@ -74,6 +83,12 @@
+ 	count = 0;
+ 	mc = (union mcbuf *) buf;
+ 	while (fgets(line, sizeof(line), input) != NULL) {
++		if ((count + 3) >= (MAX_MICROCODE / sizeof(mc->i[0]))) {
++			printf("input file is too big");
++			rc = EXIT_FAILURE;
++			goto out;
++		}
++
+ 		if (sscanf(line, "%x, %x, %x, %x",
+ 		    &mc->i[count],
+ 		    &mc->i[count + 1],
+@@ -102,6 +117,10 @@
+ 		unsigned int family, model, stepping;
+ 		unsigned int year, month, day;
+ 
++		if ((start > bufsize) ||
++		    ((bufsize - start) < sizeof(struct microcode_header_intel)))
++			goto out;
++
+ 		mc = (union mcbuf *) &buf[start];
+ 
+ 		if (mc->hdr.totalsize)
+@@ -109,8 +128,12 @@
+ 		else
+ 			size = 2000 + sizeof(struct microcode_header_intel);
+ 
++		if (size > (bufsize - start))
++			goto out;
++
+ 		if (mc->hdr.ldrver != 1 || mc->hdr.hdrver != 1) {
+-			printf("unknown version/format:\n");
++			printf("unknown version/format: %d/%d\n",
++			       mc->hdr.ldrver, mc->hdr.hdrver);
+ 			rc = EXIT_FAILURE;
+ 			break;
+ 		}
+@@ -135,7 +158,11 @@
+ 		month = mc->hdr.date >> 24;
+ 		day = (mc->hdr.date >> 16) & 0xff;
+ 
+-		asprintf(&filename, "intel-ucode/%02x-%02x-%02x", family, model, stepping);
++		if (asprintf(&filename, "intel-ucode/%02x-%02x-%02x", family,
++		    model, stepping) == -1) {
++			printf("Failed to generate ucode filename\n");
++			goto out;
++		}
+ 		printf("\n");
+ 		printf("%s\n", filename);
+ 		printf("signature: 0x%02x\n", mc->hdr.sig);
+@@ -164,6 +191,11 @@
+ 	}
+ 	printf("\n");
+ 
++	if (start != bufsize)
++		printf("Finished parsing at byte %zu of %zu\n", start, bufsize);
++
+  out:
++	free(buf);
++
+ 	return rc;
+ }
diff --git a/SOURCES/microcode_ctl-use-microcode-20180807a-tgz.patch b/SOURCES/microcode_ctl-use-microcode-20180807a-tgz.patch
new file mode 100644
index 0000000..f39cb1f
--- /dev/null
+++ b/SOURCES/microcode_ctl-use-microcode-20180807a-tgz.patch
@@ -0,0 +1,13 @@
+Index: microcode_ctl-2.1-18/Makefile
+===================================================================
+--- microcode_ctl-2.1-18.orig/Makefile	2018-07-24 09:15:12.463115045 +0200
++++ microcode_ctl-2.1-18/Makefile	2018-08-09 06:18:45.524503945 +0200
+@@ -8,7 +8,7 @@
+ # 2 of the License, or (at your option) any later version.
+ 
+ PROGRAM         = intel-microcode2ucode
+-MICROCODE_INTEL = microcode-20171117.tgz
++MICROCODE_INTEL = microcode-20180807a.tgz
+ 
+ INS             = install
+ CC              = gcc
diff --git a/SOURCES/reload_microcode b/SOURCES/reload_microcode
index 62fb43e..82ff2b9 100644
--- a/SOURCES/reload_microcode
+++ b/SOURCES/reload_microcode
@@ -6,8 +6,16 @@
 # SPDX-License-Identifier: CC0-1.0
 
 CHECK_CAVEATS=/usr/libexec/microcode_ctl/check_caveats
+IGNORE_HYPERVISOR="/etc/microcode_ctl/ignore-hypervisor-flag"
 trigger=1
 
+[ -e "$IGNORE_HYPERVISOR" ] || {
+	if grep -q '^flags[[:space:]]*:.* hypervisor\( .*\)\?$' /proc/cpuinfo
+	then
+		exit 0
+	fi
+}
+
 "$CHECK_CAVEATS" -m > /dev/null || trigger=0
 
 [ 0 -eq "$trigger" ] || echo 2>/dev/null 1 > /sys/devices/system/cpu/microcode/reload || true
diff --git a/SOURCES/update_ucode b/SOURCES/update_ucode
index df8033f..431148a 100644
--- a/SOURCES/update_ucode
+++ b/SOURCES/update_ucode
@@ -7,9 +7,10 @@
 
 usage()
 {
-	echo "Usage: update_ucode [--action {add|remove|refresh}]" \
+	echo "Usage: update_ucode [--action {add|remove|refresh|list}]" \
 	     "[--kernel KERNELVER]* [--verbose] [--dry-run]" \
-	     "[--trigger-dracut] [--cleanup intel_ucode caveats_ucode]" >&2
+	     "[--cleanup intel_ucode caveats_ucode]" \
+	     "[--skip-common] [--skip-kernel-specific]" >&2
 }
 
 debug() { [ 0 = "$verbose" ] || echo "$*" >&2; }
@@ -25,13 +26,20 @@ kernel=
 verbose=0
 verbose_opt=
 dry_run=0
-trigger_dracut=0
 remove_cleanup=0
 cleanup_intel=
 cleanup_caveats=
+skip_common=0
+skip_caveats=0
 
 while [ 1 -le "$#" ]; do
 	case "$1" in
+	-C|--skip-common)
+		skip_common=1
+		;;
+	-K|--skip-kernel-specific)
+		skip_caveats=1
+		;;
 	-a|--action)
 		shift
 		action="$1"
@@ -47,9 +55,6 @@ while [ 1 -le "$#" ]; do
 	-n|--dry-run)
 		dry_run=1
 		;;
-	-d|--trigger-dracut)
-		trigger_dracut=1
-		;;
 	-c|--cleanup)
 		remove_cleanup=1
 		shift
@@ -69,7 +74,7 @@ cmd=
 [ 0 -eq "$dry_run" ] || cmd=echo
 
 case "$action" in
-add|remove|refresh)
+add|remove|refresh|list)
 	# Scan all directories in FW_DIR and all existing kernels
 	if [ -z "$kernel" ]; then
 		debug "No kernel versions provided, scanning..."
@@ -91,6 +96,8 @@ add|remove|refresh)
 				kernel="$kernel $k"
 			}
 		done
+
+		kernel=$(printf "%s" "$kernel" | xargs -n 1 | sort -u)
 	fi
 	;;
 *)
@@ -103,6 +110,8 @@ esac
 # Generic part: managing intel ucode
 debug "Running action \"$action\" on common Intel microcode directory"
 while :; do
+	[ 0 -eq "$skip_common" ] || break
+
 	[ ! -e "/etc/microcode_ctl/intel-ucode-disallow" ] || {
 		debug "  Skipping \"$i\":" \
 		      "\"/etc/microcode_ctl/intel-ucode-disallow\"" \
@@ -117,8 +126,8 @@ while :; do
 
 	# Removing old files
 	case "$action" in
-	refresh|remove)
-		debug "  Removing old files from ${MC_DIR}/${INTEL_UCODE_DIR}"
+	refresh|remove|list)
+		debug "  Removing old files from ${FW_DIR}/${INTEL_UCODE_DIR}"
 		if [ 0 = "$remove_cleanup" ]; then
 			find "${MC_DIR}/${INTEL_UCODE_DIR}" \
 				-maxdepth 1 -mindepth 1 \
@@ -134,23 +143,25 @@ while :; do
 				[ -L "$name" ] || continue
 			fi
 
+			[ "xlist" != "x$action" ] || {
+				echo "$name"
+				continue
+			}
+
 			$cmd rm -f $verbose_opt "$name"
 		done
-		$cmd rmdir -p $verbose_opt "${FW_DIR}/${INTEL_UCODE_DIR}" 2>/dev/null || true
+		[ "xlist" = "x$action" ] || {
+			$cmd rmdir -p $verbose_opt \
+				"${FW_DIR}/${INTEL_UCODE_DIR}" 2>/dev/null \
+				|| true
+		}
 		;;
 	esac
 
 	# Adding new ones
 	case "$action" in
 	add|refresh)
-		if grep -q '^flags[[:space:]]*:.*hypervisor' /proc/cpuinfo; then
-			debug "  A virtualised environment has been detected" \
-			      "(hypervisor flag is present in /proc/cpuinfo)," \
-			      "skipping"
-			break
-		fi
-
-		debug "  Creating symlinks in ${MC_DIR}/${INTEL_UCODE_DIR}"
+		debug "  Creating symlinks in ${FW_DIR}/${INTEL_UCODE_DIR}"
 		$cmd mkdir -p $verbose_opt "${FW_DIR}/${INTEL_UCODE_DIR}"
 		$cmd find "${MC_DIR}/${INTEL_UCODE_DIR}" -maxdepth 1 -mindepth 1 \
 			-type f -exec bash -c 'ln -s '"$verbose_opt"' '\''{}'\'' \
@@ -168,87 +179,110 @@ if [ 0 = "$remove_cleanup" ]; then
 else
 	cat "$cleanup_caveats"
 fi | while read -r i; do
+	[ 0 -eq "$skip_caveats" ] || break
+
 	debug "Processing data directory \"$i\"..."
-	[ -e "$DATA_DIR/$i/readme" ] || {
-		debug "  Skipping \"$i\": no readme"
-		continue
-	}
-	[ -e "$DATA_DIR/$i/config" ] || {
-		debug "  Skipping \"$i\": no config"
-		continue
-	}
-	[ ! -e "/etc/microcode_ctl/ucode_with_caveats/disallow-$i" ] || {
-		debug "  Skipping \"$i\":" \
-		      "\"/etc/microcode_ctl/ucode_with_caveats/disallow-$i\"" \
-		      "present"
-		continue
-	}
 
 	for k in $(echo "$kernel"); do
 		debug "    Processing kernel version \"$k\""
-		$check_caveats -k "$k" -c "$i" $verbose_opt > /dev/null || {
-			debug "    Checking for caveats failed" \
-			      "(kernel version \"$k\"), skipping"
+		{
+			out=$($check_caveats -k "$k" -c "$i" $verbose_opt)
+			ret="$?"
+		} || :
+		paths=$(printf "%s" "$out" | sed -n 's/^paths //p')
+		ignore=$(printf "%s" "$out" | sed -n 's/^skip_cfgs //p')
+
+		[ -z "$ignore" ] || {
+			debug "      Configuration is ignored, skipping"
 			continue
 		}
-		path=$($check_caveats -k "$k" -c "$i")
 
 		case "$action" in
-		remove|refresh)
-			debug "    Removing $path (part of $action)..."
+		remove|refresh|list)
+			[ "xlist" = "x$action" ] || \
+				debug "    Removing \"$paths\" (part of $action)..."
 
-			if [ -e "$FW_DIR/$k/readme-$i" ]; then
-				debug "      Removing \"$FW_DIR/$k/$path\""
-				$cmd rm -f $verbose_opt "$FW_DIR/$k/$path"
-				$cmd rm -f $verbose_opt "$FW_DIR/$k/readme-$i"
-				$cmd rmdir -p $verbose_opt "$(dirname "$FW_DIR/$k/$path")" 2>/dev/null || true
-
-				[ 0 -eq "$trigger_dracut" ] || {
-					debug "      Triggering dracut for kernel \"$k\""
-					$cmd dracut -f $verbose_opt --kver "$k"
+			for p in $(printf "%s" "$paths"); do
+				find "$DATA_DIR/$i" -path "$DATA_DIR/$i/$p" \
+					-printf "%P\n"
+			done | while read -r path; do
+				[ -e "$FW_DIR/$k/readme-$i" ] || {
+					debug "      \"$FW_DIR/$k/readme-$i\"" \
+					      "is not found, skipping" \
+					      "\"$paths\" removal"
+
+					break
 				}
-			else
-				debug "      \"$FW_DIR/$k/readme-$i\" is not found," \
-				      "skipping \"$FW_DIR/$k/$path\" removal"
+
+				if [ "xlist" = "x$action" ]; then
+					echo "$FW_DIR/$k/$path"
+				else
+					debug "      Removing \"$FW_DIR/$k/$path\""
+					$cmd rm -f $verbose_opt "$FW_DIR/$k/$path"
+					$cmd rmdir -p $verbose_opt \
+						"$FW_DIR/$k/$(dirname $path)" 2>/dev/null \
+						|| true
+				fi
+			done
+
+			if [ -e "$FW_DIR/$k/readme-$i" ]; then
+				if [ "xlist" = "x$action" ]; then
+					echo "$FW_DIR/$k/readme-$i"
+				else
+					$cmd rm -f $verbose_opt \
+						"$FW_DIR/$k/readme-$i"
+					$cmd rmdir -p $verbose_opt \
+						"$FW_DIR/$k" 2>/dev/null || true
+				fi
 			fi
 			;;
 		esac
 
+		[ 0 -eq "$ret" ] || {
+			debug "    Checking for caveats failed" \
+			      "(kernel version \"$k\"), skipping"
+			continue
+		}
+
+		[ -n "$paths" ] || {
+			debug "    List of paths to add is empty, skipping"
+			continue
+		}
+
 		case "$action" in
 		add|refresh)
-			debug "    Adding $path (part of $action)..."
+			debug "    Adding $paths (part of $action)..."
 
 			[ -e "/boot/symvers-$k.gz" ] || {
 				debug "      \"/boot/symvers-$k.gz\"" \
 				      "does not exist, skipping"
 				continue
 			}
-			if grep -q '^flags[[:space:]]*:.*hypervisor' /proc/cpuinfo; then
-				debug "      A virtualised environment has been detected" \
-				      "(hypervisor flag is present in /proc/cpuinfo)," \
-				      "skipping"
-				break
-			fi
-			[ ! -e "$FW_DIR/$k/disallow-$i" ] || {
-				debug "      Found \"$FW_DIR/$k/disallow-$i\"," \
-				      "skipping"
-				continue
-			}
-			[ ! -e "$FW_DIR/$k/$path" ] || {
-				debug "      \"$FW_DIR/$k/$path\" already exists," \
-				      "skipping"
-				continue
-			}
 
-			debug "      Adding \"$FW_DIR/$k/$path\""
-			$cmd mkdir -p "$(dirname "$FW_DIR/$k/$path")"
-			$cmd ln -s "$DATA_DIR/$i/$path" "$FW_DIR/$k/$path"
-			$cmd cp "$DATA_DIR/$i/readme" "$FW_DIR/$k/readme-$i"
+			for p in $(printf "%s" "$paths"); do
+				find "$DATA_DIR/$i" -path "$DATA_DIR/$i/$p" \
+					-printf "%P\n"
+			done | while read -r path; do
+				[ ! -e "$FW_DIR/$k/$path" ] || {
+					debug "      $FW_DIR/$k/$path already" \
+					      "exists, skipping"
+					continue
+				}
+
+				debug "      Adding \"$FW_DIR/$k/$path\""
+				$cmd mkdir -p $verbose_opt \
+					"$(dirname "$FW_DIR/$k/$path")"
+				$cmd ln -s $verbose_opt "$DATA_DIR/$i/$path" \
+					"$FW_DIR/$k/$path"
+			done
 
-			[ 0 -eq "$trigger_dracut" ] || {
-				debug "      Triggering dracut for kernel \"$k\""
-				$cmd dracut -f $verbose_opt --kver "$k"
-			}
+			if [ -e "$FW_DIR/$k/readme-$i" ]; then
+				debug "        $FW_DIR/$k/readme-$i already" \
+				      "exists, skipping creation"
+			else
+				$cmd cp $verbose_opt "$DATA_DIR/$i/readme" \
+					"$FW_DIR/$k/readme-$i"
+			fi
 			;;
 		remove)
 		esac
diff --git a/SPECS/microcode_ctl.spec b/SPECS/microcode_ctl.spec
index 102109d..e1a6ac9 100644
--- a/SPECS/microcode_ctl.spec
+++ b/SPECS/microcode_ctl.spec
@@ -1,27 +1,47 @@
-%define upstream_version 2.1-20180703
-%define microcode_ctl_libexec /usr/libexec/microcode_ctl
+%define upstream_version 2.1-14
+%define intel_ucode_version 20180807a
+%define intel_ucode_file_id 28087
+%define microcode_ctl_libexec %{_libexecdir}/microcode_ctl
 %define update_ucode %{microcode_ctl_libexec}/update_ucode
 %define check_caveats %{microcode_ctl_libexec}/check_caveats
 %define reload_microcode %{microcode_ctl_libexec}/reload_microcode
+%define dracutlibdir %{_prefix}/lib/dracut
+%define i_m2u_man intel-microcode2ucode.8
 
 Summary:        Tool to transform and deploy CPU microcode update for x86.
 Name:           microcode_ctl
 Version:        2.1
-Release:        29.10%{?dist}
+Release:        29.16%{?dist}
 Epoch:          2
 Group:          System Environment/Base
 License:        GPLv2+ and Redistributable, no modification permitted
 URL:            https://pagure.io/microcode_ctl
-Source0:        %{name}-%{upstream_version}.tar.xz
-Source1:        microcode.service
-Source2:        01-microcode.conf
-Source3:        disclaimer
-Source4:        update_ucode
-Source5:        check_caveats
-Source6:        reload_microcode
-Source7:        dracut_99microcode_ctl-fw_dir_override_module_init.sh
-Source8:        06-4f-01_readme
-Source9:        06-4f-01_config
+Source0:        https://releases.pagure.org/microcode_ctl/%{name}-%{upstream_version}.tar.xz
+Source1:        https://downloadmirror.intel.com/%{intel_ucode_file_id}/eng/microcode-%{intel_ucode_version}.tgz
+
+Source2:        microcode.service
+
+Source3:        01-microcode.conf
+Source4:        dracut_99microcode_ctl-fw_dir_override_module_init.sh
+
+Source5:        update_ucode
+Source6:        check_caveats
+Source7:        reload_microcode
+Source8:        disclaimer
+
+Source10:       06-4f-01_readme
+Source11:       06-4f-01_config
+
+Source20:       intel_readme
+Source21:       intel_config
+
+Source30:       README.caveats
+Source31:       %{i_m2u_man}.in
+
+Patch1:         microcode_ctl-do-not-pipe-to-intel_microcode2ucode.patch
+Patch2:         microcode_ctl-use-microcode-%{intel_ucode_version}-tgz.patch
+Patch4:         microcode_ctl-do-not-install-intel-ucode.patch
+Patch5:         microcode_ctl-intel-microcode2ucode-buf-handling.patch
 
 Buildroot:      %{_tmppath}/%{name}-%{version}-root
 ExclusiveArch:  %{ix86} x86_64
@@ -41,45 +61,91 @@ back to the old microcode.
 
 %prep
 %setup -q -n %{name}-%{upstream_version}
+%patch1 -p1
+
+# Use microcode-20180807a.tgz instead of microcode-20171117.tgz bundled with
+# upstream microcode_ctl-2.1-14.
+cp "%{SOURCE1}" .
+%patch2 -p1
+
+# We install ucode files manually into "intel" caveat directory
+%patch4 -p1
+
+%patch5 -p1
 
 %build
 make CFLAGS="$RPM_OPT_FLAGS" %{?_smp_mflags}
 
-find intel-ucode -type f | sed 's/^/%%ghost \/lib\/firmware\//' > ghost_list
+# We do not populate any intel-ucode files into /lib/firmware directly due to
+# early microcode load inside VM issue:
+#   https://bugzilla.redhat.com/show_bug.cgi?id=1596627
+#   https://bugzilla.redhat.com/show_bug.cgi?id=1607899
+#find intel-ucode -type f | sed 's/^/%%ghost \/lib\/firmware\//' > ghost_list
+touch ghost_list
+
+# man page
+sed "%{SOURCE31}" \
+	-e "s/@DATE@/2018-08-28/g" \
+	-e "s/@VERSION@/%{version}-%{release}/g" \
+	-e "s|@MICROCODE_URL@|https://downloadcenter.intel.com/download/%{intel_ucode_file_id}|g" > "%{i_m2u_man}"
 
 %install
 rm -rf %{buildroot}
 make DESTDIR=%{buildroot} PREFIX=%{_prefix} INSDIR=/usr/sbin MICDIR=/usr/share/microcode_ctl install clean
 
-mkdir -p %{buildroot}/usr/lib/dracut/dracut.conf.d
+mkdir -p %{buildroot}%{dracutlibdir}/dracut.conf.d
 mkdir -p %{buildroot}%{_unitdir}
-install -m 644 %{SOURCE1} %{buildroot}%{_unitdir}
-install -m 644 %{SOURCE2} %{buildroot}/usr/lib/dracut/dracut.conf.d
-install -m 644 %{SOURCE3} %{buildroot}/usr/share/doc/microcode_ctl/disclaimer
+install -m 644 %{SOURCE2} -t %{buildroot}%{_unitdir}
+install -m 644 %{SOURCE3} -t %{buildroot}%{dracutlibdir}/dracut.conf.d
+install -m 644 %{SOURCE8} %{buildroot}/usr/share/doc/microcode_ctl/disclaimer
 
+mkdir -p "%{buildroot}%{dracutlibdir}/modules.d/99microcode_ctl-fw_dir_override"
+install -m 755 %{SOURCE4} \
+	%{buildroot}%{dracutlibdir}/modules.d/99microcode_ctl-fw_dir_override/module-setup.sh
+
+# Internal helper scripts
 mkdir -p %{buildroot}/%{microcode_ctl_libexec}
-install -m 755 %{SOURCE4} %{buildroot}/%{update_ucode}
-install -m 755 %{SOURCE5} %{buildroot}/%{check_caveats}
-install -m 755 %{SOURCE6} %{buildroot}/%{reload_microcode}
+install -m 755 %{SOURCE5} %{buildroot}/%{update_ucode}
+install -m 755 %{SOURCE6} %{buildroot}/%{check_caveats}
+install -m 755 %{SOURCE7} %{buildroot}/%{reload_microcode}
 
-mkdir -p "%{buildroot}/usr/lib/dracut/modules.d/99microcode_ctl-fw_dir_override"
-install -m 755 %{SOURCE7} %{buildroot}/usr/lib/dracut/modules.d/99microcode_ctl-fw_dir_override/module-setup.sh
+# caveats readme
+install -m 644 %{SOURCE30} -t %{buildroot}/usr/share/doc/microcode_ctl/
 
-mkdir -p "%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/intel-ucode"
-install -m 644 intel-ucode-with-caveats/06-4f-01 %{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/intel-ucode/06-4f-01
-install -m 644 %{SOURCE8} %{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/readme
-install -m 644 %{SOURCE9} %{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/config
+# Provide Intel microcode license, as it requires so
+install -m 644 license %{buildroot}/usr/share/doc/microcode_ctl/LICENSE.intel-ucode
 
+# Handle ucode with caveats
+mkdir -p "%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/intel-ucode"
+install -m 644 intel-ucode-with-caveats/06-4f-01 \
+	-t %{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/intel-ucode/
+install -m 644 %{SOURCE10} \
+	%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/readme
+install -m 644 %{SOURCE11} \
+	%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel-06-4f-01/config
+
+mkdir -p "%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel/intel-ucode"
+install -m 644 intel-ucode/* \
+	-t %{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel/intel-ucode/
+install -m 644 %{SOURCE20} \
+	%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel/readme
+install -m 644 %{SOURCE21} \
+	%{buildroot}/usr/share/microcode_ctl/ucode_with_caveats/intel/config
+
+# Man page
+install -m 755 -d %{buildroot}/%{_mandir}/man8/
+install -m 644 "%{i_m2u_man}" -t %{buildroot}/%{_mandir}/man8/
+
+# Cleanup
 rm -f intel-ucode-with-caveats/06-4f-01
 rmdir intel-ucode-with-caveats
+rm -rf intel-ucode
 
 %post
 %systemd_post microcode.service
 %{update_ucode}
-# "reload" file is not presented on a certain virtualized hw
-if [ -w /sys/devices/system/cpu/microcode/reload ] ; then
-	%{reload_microcode}
-fi
+%{reload_microcode}
+
 # send the message to syslog, so it gets recorded on /var/log
 if [ -e /usr/bin/logger ]; then
 	/usr/bin/logger -p syslog.notice -t DISCLAIMER -f /usr/share/doc/microcode_ctl/disclaimer
@@ -95,7 +161,12 @@ cat /usr/share/doc/microcode_ctl/disclaimer > /dev/kmsg
 # dependency, it is pointless at best to regenerate the initramfs,
 # and also does not work with rpm-ostree:
 # https://bugzilla.redhat.com/show_bug.cgi?id=1199582
-if [ -d /run/systemd/system ]; then
+#
+# Also check that the running kernel is actually installed:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1591664
+# We use the presence of symvers file as an indicator, the check similar
+# to what weak-modules script does.
+if [ -d /run/systemd/system -a -e "/boot/symvers-$(uname -r).gz" ]; then
 	dracut -f
 fi
 
@@ -107,44 +178,61 @@ ls /usr/share/microcode_ctl/intel-ucode |
 	sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode"
 ls /usr/share/microcode_ctl/ucode_with_caveats |
 	sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats"
+%{update_ucode} --action list --skip-common |
+	sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_file_list"
 
 %postun
 %systemd_postun microcode.service
 
-ls /usr/share/microcode_ctl/intel-ucode 2> /dev/null |
-	sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after"
-ls /usr/share/microcode_ctl/ucode_with_caveats 2> /dev/null |
-	sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after"
+if [ -e "%{update_ucode}" ]; then
+	ls /usr/share/microcode_ctl/intel-ucode 2> /dev/null |
+		sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after"
+	ls /usr/share/microcode_ctl/ucode_with_caveats 2> /dev/null |
+		sort > "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after"
 
-comm -23 \
-	"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode" \
-	"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after" \
-	> "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff"
+	comm -23 \
+		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode" \
+		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after" \
+		> "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff"
 
-comm -23 \
-	"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats" \
-	"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after" \
-	> "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff"
+	comm -23 \
+		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats" \
+		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after" \
+		> "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff"
 
-if [ -e "%{update_ucode}" ]; then
 	%{update_ucode} --action remove --cleanup \
 		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff" \
 		"%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff" || exit 0
+
+	rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after"
+	rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after"
+
+	rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff"
+	rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff"
 else
-	while read f; do
+	while read -r f; do
 		[ -L "/lib/firmware/intel-ucode/$f" ] || continue
 		rm -f "/lib/firmware/intel-ucode/$f"
 	done < "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff"
+
+	rmdir "/lib/firmware/intel-ucode" 2>/dev/null || :
+
+	# We presume that if we don't have update_ucode script, we can remove
+	# all the caveats-related files.
+	while read -r f; do
+		if [ -L "$f" ] || [ "${f%%readme-*}" != "$f" ]; then
+			rm -f "$f"
+			rmdir -p $(dirname "$f") 2>/dev/null || :
+		fi
+	done < "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_file_list"
 fi
 
 rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode"
 rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats"
 
-rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_after"
-rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_after"
+rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_file_list"
 
-rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_intel-ucode_diff"
-rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff"
+exit 0
 
 %triggerin -- kernel
 %{update_ucode}
@@ -157,17 +245,41 @@ rm -f "%{_localstatedir}/lib/rpm-state/microcode_ctl_un_ucode_caveats_diff"
 rm -rf %{buildroot}
 
 %files -f ghost_list
-%ghost %attr(0100755, root, root) /lib/firmware/intel-ucode/
+%ghost %attr(0755, root, root) /lib/firmware/intel-ucode/
 /usr/sbin/intel-microcode2ucode
 %{microcode_ctl_libexec}
 /usr/share/microcode_ctl
-/usr/lib/dracut/modules.d/99microcode_ctl-fw_dir_override
-%config(noreplace) /usr/lib/dracut/dracut.conf.d/01-microcode.conf
+%{dracutlibdir}/modules.d/99microcode_ctl-fw_dir_override
+%config(noreplace) %{dracutlibdir}/dracut.conf.d/01-microcode.conf
 %{_unitdir}/microcode.service
 %doc /usr/share/doc/microcode_ctl/*
+%{_mandir}/man8/*
 
 
 %changelog
+* Wed Sep 05 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.16
+- Add 7.3.z kernel version to kernel_early configuration.
+
+* Thu Aug 30 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.15
+- Fix dracut module checks in Host-Only mode.
+
+* Thu Aug 30 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.14
+- Disable 06-4f-01 microcode in config (#1623630).
+
+* Wed Aug 29 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.12
+- Drop "hypervisor" /proc/cpuinfo flag check.
+- Intel CPU microcode update to 20180807a.
+- Add README.caveats documentation file.
+- Add intel-microcode2ucode manual page.
+- Add check for early microcode load, use it in microcode_ctl dracut module.
+- Check that the currently running kernel is installed before
+  running dracut -f.
+
+* Fri Aug 10 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.11
+- Add an ability to disable "hypervisor" /proc/cpuinfo flag check.
+- Intel CPU microcode update to 20180807.
+- Resolves: #1614847.
+
 * Fri Jul 27 2018 Eugene Syromiatnikov <esyr@redhat.com> - 2:2.1-29.10
 - Provide %attr for the ghosted /lib/firmware.