Merge "logd: Move the capabilities from file based to ambient"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index dc45959..e6f8716 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -74,3 +74,6 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/ld.config.txt)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/llndk.libraries.txt)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vndksp.libraries.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/ld.config.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/llndk.libraries.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vndksp.libraries.txt)
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index d5fb047..7614342 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -310,6 +310,7 @@
     {"kernel_panic,adsp", 165},
     {"kernel_panic,dsps", 166},
     {"kernel_panic,wcnss", 167},
+    {"kernel_panic,_sde_encoder_phys_cmd_handle_ppdone_timeout", 168},
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6e9ffba..9856126 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1190,27 +1190,6 @@
     return 0;
 }
 
-int fs_mgr_unmount_all(struct fstab *fstab)
-{
-    int i = 0;
-    int ret = 0;
-
-    if (!fstab) {
-        return -1;
-    }
-
-    while (fstab->recs[i].blk_device) {
-        if (umount(fstab->recs[i].mount_point)) {
-            LERROR << "Cannot unmount filesystem at "
-                   << fstab->recs[i].mount_point;
-            ret = -1;
-        }
-        i++;
-    }
-
-    return ret;
-}
-
 /* This must be called after mount_all, because the mkswap command needs to be
  * available.
  */
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 5a9cb65..2020fa6 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -139,38 +139,23 @@
 };
 
 std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() {
-    std::string cmdline;
-    if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
-        PERROR << "Failed to read /proc/cmdline";
-        return nullptr;
-    }
-
     std::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier());
     if (!avb_verifier) {
         LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>";
         return nullptr;
     }
 
-    std::string digest;
-    std::string hash_alg;
-    for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
-        std::vector<std::string> pieces = android::base::Split(entry, "=");
-        const std::string& key = pieces[0];
-        const std::string& value = pieces[1];
-
-        if (key == "androidboot.vbmeta.hash_alg") {
-            hash_alg = value;
-        } else if (key == "androidboot.vbmeta.size") {
-            if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
-                return nullptr;
-            }
-        } else if (key == "androidboot.vbmeta.digest") {
-            digest = value;
-        }
+    std::string value;
+    if (!fs_mgr_get_boot_config("vbmeta.size", &value) ||
+        !android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
+        LERROR << "Invalid hash size: " << value.c_str();
+        return nullptr;
     }
 
     // Reads hash algorithm.
     size_t expected_digest_size = 0;
+    std::string hash_alg;
+    fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg);
     if (hash_alg == "sha256") {
         expected_digest_size = SHA256_DIGEST_LENGTH * 2;
         avb_verifier->hash_alg_ = kSHA256;
@@ -183,6 +168,8 @@
     }
 
     // Reads digest.
+    std::string digest;
+    fs_mgr_get_boot_config("vbmeta.digest", &digest);
     if (digest.size() != expected_digest_size) {
         LERROR << "Unexpected digest size: " << digest.size()
                << " (expected: " << expected_digest_size << ")";
diff --git a/fs_mgr/fs_mgr_boot_config.cpp b/fs_mgr/fs_mgr_boot_config.cpp
index 9c5d3f3..733ad55 100644
--- a/fs_mgr/fs_mgr_boot_config.cpp
+++ b/fs_mgr/fs_mgr_boot_config.cpp
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
+#include <algorithm>
+#include <iterator>
 #include <string>
+#include <vector>
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
@@ -23,46 +26,71 @@
 
 #include "fs_mgr_priv.h"
 
-// Tries to get the given boot config value from kernel cmdline.
-// Returns true if successfully found, false otherwise.
-bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) {
+std::vector<std::pair<std::string, std::string>> fs_mgr_parse_boot_config(const std::string& cmdline) {
+    static constexpr char quote = '"';
+
+    std::vector<std::pair<std::string, std::string>> result;
+    size_t base = 0;
+    while (true) {
+        // skip quoted spans
+        auto found = base;
+        while (((found = cmdline.find_first_of(" \"", found)) != cmdline.npos) &&
+               (cmdline[found] == quote)) {
+            // unbalanced quote is ok
+            if ((found = cmdline.find(quote, found + 1)) == cmdline.npos) break;
+            ++found;
+        }
+        std::string piece;
+        auto source = cmdline.substr(base, found - base);
+        std::remove_copy(source.begin(), source.end(),
+                         std::back_insert_iterator<std::string>(piece), quote);
+        auto equal_sign = piece.find('=');
+        if (equal_sign == piece.npos) {
+            if (!piece.empty()) {
+                // no difference between <key> and <key>=
+                result.emplace_back(std::move(piece), "");
+            }
+        } else {
+            result.emplace_back(piece.substr(0, equal_sign), piece.substr(equal_sign + 1));
+        }
+        if (found == cmdline.npos) break;
+        base = found + 1;
+    }
+
+    return result;
+}
+
+bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& android_key,
+                                        std::string* out_val) {
     FS_MGR_CHECK(out_val != nullptr);
 
-    std::string cmdline;
-    std::string cmdline_key("androidboot." + key);
-    if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
-        for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
-            std::vector<std::string> pieces = android::base::Split(entry, "=");
-            if (pieces.size() == 2) {
-                if (pieces[0] == cmdline_key) {
-                    *out_val = pieces[1];
-                    return true;
-                }
-            }
+    const std::string cmdline_key("androidboot." + android_key);
+    for (const auto& [key, value] : fs_mgr_parse_boot_config(cmdline)) {
+        if (key == cmdline_key) {
+            *out_val = value;
+            return true;
         }
     }
 
+    *out_val = "";
     return false;
 }
 
-// Tries to get the boot config value in properties, kernel cmdline and
-// device tree (in that order).  returns 'true' if successfully found, 'false'
-// otherwise
+// Tries to get the given boot config value from kernel cmdline.
+// Returns true if successfully found, false otherwise.
+bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) {
+    std::string cmdline;
+    if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) return false;
+    return fs_mgr_get_boot_config_from_kernel(cmdline, key, out_val);
+}
+
+// Tries to get the boot config value in device tree, properties and
+// kernel cmdline (in that order).  Returns 'true' if successfully
+// found, 'false' otherwise.
 bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) {
     FS_MGR_CHECK(out_val != nullptr);
 
-    // first check if we have "ro.boot" property already
-    *out_val = android::base::GetProperty("ro.boot." + key, "");
-    if (!out_val->empty()) {
-        return true;
-    }
-
-    // fallback to kernel cmdline, properties may not be ready yet
-    if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) {
-        return true;
-    }
-
-    // lastly, check the device tree
+    // firstly, check the device tree
     if (is_dt_compatible()) {
         std::string file_name = get_android_dt_dir() + "/" + key;
         if (android::base::ReadFileToString(file_name, out_val)) {
@@ -73,5 +101,16 @@
         }
     }
 
+    // next, check if we have "ro.boot" property already
+    *out_val = android::base::GetProperty("ro.boot." + key, "");
+    if (!out_val->empty()) {
+        return true;
+    }
+
+    // finally, fallback to kernel cmdline, properties may not be ready yet
+    if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) {
+        return true;
+    }
+
     return false;
 }
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index af4d6c1..a14dba3 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -679,7 +679,6 @@
     // We can't call fs_mgr_free_fstab because a->recs still references the
     // memory allocated by strdup.
     free(b->recs);
-    free(b->fstab_filename);
     free(b);
 
     a->num_entries = total_entries;
@@ -741,9 +740,7 @@
     }
 
     fstab = fs_mgr_read_fstab_file(fstab_file);
-    if (fstab) {
-        fstab->fstab_filename = strdup(fstab_path);
-    } else {
+    if (!fstab) {
         LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
     }
 
@@ -854,9 +851,6 @@
     /* Free the fstab_recs array created by calloc(3) */
     free(fstab->recs);
 
-    /* Free the fstab filename */
-    free(fstab->fstab_filename);
-
     /* Free fstab */
     free(fstab);
 }
diff --git a/fs_mgr/fs_mgr_priv_boot_config.h b/fs_mgr/fs_mgr_priv_boot_config.h
index d98dc02..417fb38 100644
--- a/fs_mgr/fs_mgr_priv_boot_config.h
+++ b/fs_mgr/fs_mgr_priv_boot_config.h
@@ -19,7 +19,13 @@
 
 #include <sys/cdefs.h>
 #include <string>
+#include <utility>
+#include <vector>
 
+std::vector<std::pair<std::string, std::string>> fs_mgr_parse_boot_config(const std::string& cmdline);
+
+bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& key,
+                                        std::string* out_val);
 bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val);
 bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val);
 
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 72f019e..c1b2ed9 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -70,7 +70,6 @@
                     char *tmp_mount_point);
 int fs_mgr_do_mount_one(struct fstab_rec *rec);
 int fs_mgr_do_tmpfs_mount(const char *n_name);
-int fs_mgr_unmount_all(struct fstab *fstab);
 struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
 void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
 bool fs_mgr_load_verity_state(int* mode);
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index d232cca..b1ee328 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -33,7 +33,6 @@
 struct fstab {
     int num_entries;
     struct fstab_rec* recs;
-    char* fstab_filename;
 };
 
 struct fstab_rec {
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
new file mode 100644
index 0000000..5497223
--- /dev/null
+++ b/fs_mgr/tests/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_test {
+    name: "fs_mgr_unit_test",
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+    static_libs: [
+        "libfs_mgr",
+        "libfstab",
+    ],
+
+    srcs: [
+        "fs_mgr_test.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
new file mode 100644
index 0000000..2e76752
--- /dev/null
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+
+#include "../fs_mgr_priv_boot_config.h"
+
+namespace {
+
+const std::string cmdline =
+        "rcupdate.rcu_expedited=1 rootwait ro "
+        "init=/init androidboot.bootdevice=1d84000.ufshc "
+        "androidboot.baseband=sdy androidboot.keymaster=1  skip_initramfs "
+        "androidboot.serialno=BLAHBLAHBLAH androidboot.slot_suffix=_a "
+        "androidboot.hardware.platform=sdw813 androidboot.hardware=foo "
+        "androidboot.revision=EVT1.0 androidboot.bootloader=burp-0.1-7521 "
+        "androidboot.hardware.sku=mary androidboot.hardware.radio.subtype=0 "
+        "androidboot.dtbo_idx=2 androidboot.mode=normal "
+        "androidboot.hardware.ddr=1GB,combuchi,LPDDR4X "
+        "androidboot.ddr_info=combuchiandroidboot.ddr_size=2GB "
+        "androidboot.hardware.ufs=2GB,combushi "
+        "androidboot.boottime=0BLE:58,1BLL:22,1BLE:571,2BLL:105,ODT:0,AVB:123 "
+        "androidboot.ramdump=disabled "
+        "dm=\"1 vroot none ro 1,0 10416 verity 1 624684 fec_start 624684\" "
+        "root=/dev/dm-0 "
+        "androidboot.vbmeta.device=PARTUUID=aa08f1a4-c7c9-402e-9a66-9707cafa9ceb "
+        "androidboot.vbmeta.avb_version=\"1.1\" "
+        "androidboot.vbmeta.device_state=unlocked "
+        "androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.size=5248 "
+        "androidboot.vbmeta.digest="
+        "ac13147e959861c20f2a6da97d25fe79e60e902c022a371c5c039d31e7c68860 "
+        "androidboot.vbmeta.invalidate_on_error=yes "
+        "androidboot.veritymode=enforcing androidboot.verifiedbootstate=orange "
+        "androidboot.space=\"sha256 5248 androidboot.nospace=nope\" "
+        "printk.devkmsg=on msm_rtb.filter=0x237 ehci-hcd.park=3 "
+        "\"string =\"\"string '\" "
+        "service_locator.enable=1 firmware_class.path=/vendor/firmware "
+        "cgroup.memory=nokmem lpm_levels.sleep_disabled=1 "
+        "buildvariant=userdebug  console=null "
+        "terminator=\"truncated";
+
+const std::vector<std::pair<std::string, std::string>> result_space = {
+        {"rcupdate.rcu_expedited", "1"},
+        {"rootwait", ""},
+        {"ro", ""},
+        {"init", "/init"},
+        {"androidboot.bootdevice", "1d84000.ufshc"},
+        {"androidboot.baseband", "sdy"},
+        {"androidboot.keymaster", "1"},
+        {"skip_initramfs", ""},
+        {"androidboot.serialno", "BLAHBLAHBLAH"},
+        {"androidboot.slot_suffix", "_a"},
+        {"androidboot.hardware.platform", "sdw813"},
+        {"androidboot.hardware", "foo"},
+        {"androidboot.revision", "EVT1.0"},
+        {"androidboot.bootloader", "burp-0.1-7521"},
+        {"androidboot.hardware.sku", "mary"},
+        {"androidboot.hardware.radio.subtype", "0"},
+        {"androidboot.dtbo_idx", "2"},
+        {"androidboot.mode", "normal"},
+        {"androidboot.hardware.ddr", "1GB,combuchi,LPDDR4X"},
+        {"androidboot.ddr_info", "combuchiandroidboot.ddr_size=2GB"},
+        {"androidboot.hardware.ufs", "2GB,combushi"},
+        {"androidboot.boottime", "0BLE:58,1BLL:22,1BLE:571,2BLL:105,ODT:0,AVB:123"},
+        {"androidboot.ramdump", "disabled"},
+        {"dm", "1 vroot none ro 1,0 10416 verity 1 624684 fec_start 624684"},
+        {"root", "/dev/dm-0"},
+        {"androidboot.vbmeta.device", "PARTUUID=aa08f1a4-c7c9-402e-9a66-9707cafa9ceb"},
+        {"androidboot.vbmeta.avb_version", "1.1"},
+        {"androidboot.vbmeta.device_state", "unlocked"},
+        {"androidboot.vbmeta.hash_alg", "sha256"},
+        {"androidboot.vbmeta.size", "5248"},
+        {"androidboot.vbmeta.digest",
+         "ac13147e959861c20f2a6da97d25fe79e60e902c022a371c5c039d31e7c68860"},
+        {"androidboot.vbmeta.invalidate_on_error", "yes"},
+        {"androidboot.veritymode", "enforcing"},
+        {"androidboot.verifiedbootstate", "orange"},
+        {"androidboot.space", "sha256 5248 androidboot.nospace=nope"},
+        {"printk.devkmsg", "on"},
+        {"msm_rtb.filter", "0x237"},
+        {"ehci-hcd.park", "3"},
+        {"string ", "string '"},
+        {"service_locator.enable", "1"},
+        {"firmware_class.path", "/vendor/firmware"},
+        {"cgroup.memory", "nokmem"},
+        {"lpm_levels.sleep_disabled", "1"},
+        {"buildvariant", "userdebug"},
+        {"console", "null"},
+        {"terminator", "truncated"},
+};
+
+}  // namespace
+
+TEST(fs_mgr, fs_mgr_parse_boot_config) {
+    EXPECT_EQ(result_space, fs_mgr_parse_boot_config(cmdline));
+}
+
+TEST(fs_mgr, fs_mgr_get_boot_config_from_kernel_cmdline) {
+    std::string content;
+    for (const auto& entry : result_space) {
+        static constexpr char androidboot[] = "androidboot.";
+        if (!android::base::StartsWith(entry.first, androidboot)) continue;
+        auto key = entry.first.substr(strlen(androidboot));
+        EXPECT_TRUE(fs_mgr_get_boot_config_from_kernel(cmdline, key, &content)) << " for " << key;
+        EXPECT_EQ(entry.second, content);
+    }
+    EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "vbmeta.avb_versio", &content));
+    EXPECT_TRUE(content.empty()) << content;
+    EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content));
+    EXPECT_TRUE(content.empty()) << content;
+}
diff --git a/init/init.cpp b/init/init.cpp
index 82648d9..b494bcc 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -604,47 +604,61 @@
     if (is_first_stage) {
         boot_clock::time_point start_time = boot_clock::now();
 
+        std::vector<std::pair<std::string, int>> errors;
+#define CHECKCALL(x) \
+    if (x != 0) errors.emplace_back(#x " failed", errno);
+
         // Clear the umask.
         umask(0);
 
-        clearenv();
-        setenv("PATH", _PATH_DEFPATH, 1);
+        CHECKCALL(clearenv());
+        CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
         // Get the basic filesystem setup we need put together in the initramdisk
         // on / and then we'll let the rc file figure out the rest.
-        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
-        mkdir("/dev/pts", 0755);
-        mkdir("/dev/socket", 0755);
-        mount("devpts", "/dev/pts", "devpts", 0, NULL);
-        #define MAKE_STR(x) __STRING(x)
-        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
+        CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
+        CHECKCALL(mkdir("/dev/pts", 0755));
+        CHECKCALL(mkdir("/dev/socket", 0755));
+        CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
+#define MAKE_STR(x) __STRING(x)
+        CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
+#undef MAKE_STR
         // Don't expose the raw commandline to unprivileged processes.
-        chmod("/proc/cmdline", 0440);
+        CHECKCALL(chmod("/proc/cmdline", 0440));
         gid_t groups[] = { AID_READPROC };
-        setgroups(arraysize(groups), groups);
-        mount("sysfs", "/sys", "sysfs", 0, NULL);
-        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
+        CHECKCALL(setgroups(arraysize(groups), groups));
+        CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
+        CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
 
-        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
+        CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
 
         if constexpr (WORLD_WRITABLE_KMSG) {
-            mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
+            CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
         }
 
-        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
-        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
+        CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
+        CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
 
         // Mount staging areas for devices managed by vold
         // See storage config details at http://source.android.com/devices/storage/
-        mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
-              "mode=0755,uid=0,gid=1000");
+        CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                        "mode=0755,uid=0,gid=1000"));
         // /mnt/vendor is used to mount vendor-specific partitions that can not be
         // part of the vendor partition, e.g. because they are mounted read-write.
-        mkdir("/mnt/vendor", 0755);
+        CHECKCALL(mkdir("/mnt/vendor", 0755));
+
+#undef CHECKCALL
 
         // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
         // talk to the outside world...
         InitKernelLogging(argv);
 
+        if (!errors.empty()) {
+            for (const auto& [error_string, error_errno] : errors) {
+                LOG(ERROR) << error_string << " " << strerror(error_errno);
+            }
+            LOG(FATAL) << "Init encountered errors starting first stage, aborting";
+        }
+
         LOG(INFO) << "init first stage started!";
 
         if (!DoFirstStageMount()) {
diff --git a/shell_and_utilities/README.md b/shell_and_utilities/README.md
index 678b853..b15be1f 100644
--- a/shell_and_utilities/README.md
+++ b/shell_and_utilities/README.md
@@ -18,11 +18,9 @@
 (a) didn't stand out given all the other systems-level changes and (b)
 in Marshmallow we changed direction and started the move to toybox.
 
-Not everything is provided by toybox, though. We currently still use
-the BSD dd and grep (because the toybox versions are still unfinished),
-and for the bzip2 command-line tools we use the ones that are part of
-the bzip2 distribution. The awk added in Android P is Brian Kernighan's
-"one true" awk.
+Not everything is provided by toybox, though. For the bzip2 command-line tools
+we use the ones that are part of the bzip2 distribution. The awk added in
+Android P is Brian Kernighan's "one true" awk.
 
 The lists below show what tools were provided and where they came from in
 each release starting with Gingerbread. This doesn't tell the full story,