Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c027aac7 authored by Sandeep Patil's avatar Sandeep Patil Committed by android-build-merger
Browse files

Merge changes from topic 'pre-early-mount'

am: 1549257f

Change-Id: I17bf2a322c0230f7cb368edd337e945742a10585
parents a967cf81 1549257f
Loading
Loading
Loading
Loading
+57 −2
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@
#include <stdlib.h>
#include <string.h>

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/properties.h>

#include "fs_mgr.h"
@@ -77,8 +80,51 @@ static int get_active_slot_suffix_from_misc(struct fstab *fstab,
    return 0;
}

// Gets slot_suffix from either the kernel cmdline / firmware or the
// misc partition. Sets |out_suffix| on success and returns 0. Returns
// finds slot_suffix in androidboot.slot_suffix kernel command line argument
// or in the device tree node at /firmware/android/slot_suffix property
static int get_active_slot_suffix_from_kernel(char *out_suffix,
                                              size_t suffix_len)
{
    std::string cmdline;
    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] == "androidboot.slot_suffix") {
                    strncpy(out_suffix, pieces[1].c_str(), suffix_len);
                    return 0;
                }
            }
        }
    }

    // if we can't find slot_suffix in cmdline, check the DT
    static constexpr char android_dt_dir[] = "/proc/device-tree/firmware/android";
    std::string file_name = android::base::StringPrintf("%s/compatible", android_dt_dir);
    std::string dt_value;
    if (android::base::ReadFileToString(file_name, &dt_value)) {
        if (!dt_value.compare("android,firmware")) {
            LERROR << "Error finding compatible android DT node";
            return -1;
        }

        file_name = android::base::StringPrintf("%s/%s", android_dt_dir, "slot_suffix");
        if (!android::base::ReadFileToString(file_name, &dt_value)) {
            LERROR << "Error finding slot_suffix in device tree";
            return -1;
        }

        // DT entries have a terminating '\0', so 'suffix_len' is safe.
        strncpy(out_suffix, dt_value.c_str(), suffix_len);
        return 0;
    }

    // slot_suffix missing in kernel cmdline or device tree
    return -1;
}

// Gets slot_suffix from either the kernel cmdline / device tree / firmware
// or the misc partition. Sets |out_suffix| on success and returns 0. Returns
// -1 if slot_suffix could not be determined.
static int get_active_slot_suffix(struct fstab *fstab, char *out_suffix,
                                  size_t suffix_len)
@@ -94,6 +140,15 @@ static int get_active_slot_suffix(struct fstab *fstab, char *out_suffix,
        return 0;
    }

    // if the property is not set, we are either being invoked too early
    // or the slot suffix in mentioned in the misc partition. If its
    // "too early", try to find the slotsuffix ourselves in the kernel command
    // line or the device tree
    if (get_active_slot_suffix_from_kernel(out_suffix, suffix_len) == 0) {
        LINFO << "Using slot suffix '" << out_suffix << "' from kernel";
        return 0;
    }

    // If we couldn't get the suffix from the kernel cmdline, try the
    // the misc partition.
    if (get_active_slot_suffix_from_misc(fstab, out_suffix, suffix_len) == 0) {
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(const struct fstab_rec *fstab);
int fs_mgr_is_notrim(struct fstab_rec *fstab);
int fs_mgr_is_formattable(struct fstab_rec *fstab);
int fs_mgr_is_slotselect(struct fstab_rec *fstab);
int fs_mgr_is_nofail(struct fstab_rec *fstab);
int fs_mgr_is_latemount(struct fstab_rec *fstab);
int fs_mgr_is_quota(struct fstab_rec *fstab);
+96 −100
Original line number Diff line number Diff line
@@ -62,19 +62,7 @@ static const char *firmware_dirs[] = { "/etc/firmware",

extern struct selabel_handle *sehandle;

static int device_fd = -1;

struct uevent {
    const char *action;
    const char *path;
    const char *subsystem;
    const char *firmware;
    const char *partition_name;
    const char *device_name;
    int partition_num;
    int major;
    int minor;
};
static android::base::unique_fd device_fd;

struct perms_ {
    char *name;
@@ -249,11 +237,13 @@ static void make_device(const char *path,

    mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);

    if (sehandle) {
        if (selabel_lookup_best_match(sehandle, &secontext, path, links, mode)) {
            PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label";
            return;
        }
        setfscreatecon(secontext);
    }

    dev = makedev(major, minor);
    /* Temporarily change egid to avoid race condition setting the gid of the
@@ -264,7 +254,7 @@ static void make_device(const char *path,
    setegid(gid);
    /* If the node already exists update its SELinux label to handle cases when
     * it was created with the wrong context during coldboot procedure. */
    if (mknod(path, mode, dev) && (errno == EEXIST)) {
    if (mknod(path, mode, dev) && (errno == EEXIST) && secontext) {

        char* fcon = nullptr;
        int rc = lgetfilecon(path, &fcon);
@@ -285,9 +275,11 @@ out:
    chown(path, uid, -1);
    setegid(AID_ROOT);

    if (secontext) {
        freecon(secontext);
        setfscreatecon(NULL);
    }
}

static void add_platform_device(const char *path)
{
@@ -349,6 +341,19 @@ static void remove_platform_device(const char *path)
    }
}

static void destroy_platform_devices() {
    struct listnode* node;
    struct listnode* n;
    struct platform_node* bus;

    list_for_each_safe(node, n, &platform_names) {
        list_remove(node);
        bus = node_to_item(node, struct platform_node, list);
        free(bus->path);
        free(bus);
    }
}

/* Given a path that may start with a PCI device, populate the supplied buffer
 * with the PCI domain/bus number and the peripheral ID and return 0.
 * If it doesn't start with a PCI device, or there is some error, return -1 */
@@ -515,7 +520,7 @@ static char **get_block_device_symlinks(struct uevent *uevent)
        return NULL;
    memset(links, 0, sizeof(char *) * 4);

    LOG(INFO) << "found " << type << " device " << device;
    LOG(VERBOSE) << "found " << type << " device " << device;

    snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device);

@@ -875,9 +880,15 @@ static void handle_firmware_event(uevent* uevent) {
    }
}

static bool inline should_stop_coldboot(coldboot_action_t act)
{
    return (act == COLDBOOT_STOP || act == COLDBOOT_FINISH);
}

#define UEVENT_MSG_LEN  2048

static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
static inline coldboot_action_t handle_device_fd_with(
        std::function<coldboot_action_t(uevent* uevent)> handle_uevent)
{
    char msg[UEVENT_MSG_LEN+2];
    int n;
@@ -890,14 +901,18 @@ static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))

        struct uevent uevent;
        parse_event(msg, &uevent);
        handle_uevent(&uevent);
        coldboot_action_t act = handle_uevent(&uevent);
        if (should_stop_coldboot(act))
            return act;
    }

    return COLDBOOT_CONTINUE;
}

void handle_device_fd()
coldboot_action_t handle_device_fd(coldboot_callback fn)
{
    handle_device_fd_with(
        [](struct uevent *uevent) {
    coldboot_action_t ret = handle_device_fd_with(
        [&](uevent* uevent) -> coldboot_action_t {
            if (selinux_status_updated() > 0) {
                struct selabel_handle *sehandle2;
                sehandle2 = selinux_android_file_context_handle();
@@ -907,9 +922,21 @@ void handle_device_fd()
                }
            }

            // default is to always create the devices
            coldboot_action_t act = COLDBOOT_CREATE;
            if (fn) {
                act = fn(uevent);
            }

            if (act == COLDBOOT_CREATE || act == COLDBOOT_STOP) {
                handle_device_event(uevent);
                handle_firmware_event(uevent);
            }

            return act;
        });

    return ret;
}

/* Coldboot walks parts of the /sys tree and pokes the uevent files
@@ -921,10 +948,11 @@ void handle_device_fd()
** socket's buffer.
*/

static void do_coldboot(DIR *d)
static coldboot_action_t do_coldboot(DIR *d, coldboot_callback fn)
{
    struct dirent *de;
    int dfd, fd;
    coldboot_action_t act = COLDBOOT_CONTINUE;

    dfd = dirfd(d);

@@ -932,10 +960,12 @@ static void do_coldboot(DIR *d)
    if (fd >= 0) {
        write(fd, "add\n", 4);
        close(fd);
        handle_device_fd();
        act = handle_device_fd(fn);
        if (should_stop_coldboot(act))
            return act;
    }

    while((de = readdir(d))) {
    while (!should_stop_coldboot(act) && (de = readdir(d))) {
        DIR *d2;

        if(de->d_type != DT_DIR || de->d_name[0] == '.')
@@ -949,85 +979,31 @@ static void do_coldboot(DIR *d)
        if(d2 == 0)
            close(fd);
        else {
            do_coldboot(d2);
            act = do_coldboot(d2, fn);
            closedir(d2);
        }
    }

    // default is always to continue looking for uevents
    return act;
}

static void coldboot(const char *path)
static coldboot_action_t coldboot(const char *path, coldboot_callback fn)
{
    std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path), closedir);
    if (d) {
        do_coldboot(d.get());
    }
        return do_coldboot(d.get(), fn);
    }

static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
{
    const char *name;
    char devpath[DEVPATH_LEN];

    if (is_block && strncmp(uevent->subsystem, "block", 5))
        return;

    name = parse_device_name(uevent, MAX_DEV_NAME);
    if (!name) {
        LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
                   << " " << uevent->partition_name << " " << uevent->partition_num
                   << " " << uevent->major << ":" << uevent->minor;
        return;
    return COLDBOOT_CONTINUE;
}

    snprintf(devpath, sizeof(devpath), "%s%s", base, name);
    make_dir(base, 0755);

    dev_t dev = makedev(uevent->major, uevent->minor);
    mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
    mknod(devpath, mode, dev);
}

void early_create_dev(const std::string& syspath, early_device_type dev_type)
{
    android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
    if (dfd < 0) {
        LOG(ERROR) << "Failed to open " << syspath;
        return;
    }

    android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
    if (fd < 0) {
        LOG(ERROR) << "Failed to open " << syspath << "/uevent";
        return;
    }

    fcntl(device_fd, F_SETFL, O_NONBLOCK);

    write(fd, "add\n", 4);
    handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
        [](struct uevent *uevent) {
            early_uevent_handler(uevent, "/dev/block/", true);
        } :
        [](struct uevent *uevent) {
            early_uevent_handler(uevent, "/dev/", false);
        });
}

int early_device_socket_open() {
    device_fd = uevent_open_socket(256*1024, true);
    return device_fd < 0;
}

void early_device_socket_close() {
    close(device_fd);
}

void device_init() {
void device_init(const char* path, coldboot_callback fn) {
    sehandle = selinux_android_file_context_handle();
    selinux_status_open(true);

    /* is 256K enough? udev uses 16MB! */
    device_fd = uevent_open_socket(256*1024, true);
    device_fd.reset(uevent_open_socket(256*1024, true));
    if (device_fd == -1) {
        return;
    }
@@ -1039,13 +1015,33 @@ void device_init() {
    }

    Timer t;
    coldboot("/sys/class");
    coldboot("/sys/block");
    coldboot("/sys/devices");
    coldboot_action_t act;
    if (!path) {
        act = coldboot("/sys/class", fn);
        if (!should_stop_coldboot(act)) {
            act = coldboot("/sys/block", fn);
            if (!should_stop_coldboot(act)) {
                act = coldboot("/sys/devices", fn);
            }
        }
    } else {
        act = coldboot(path, fn);
    }

    // If we have a callback, then do as it says. If no, then the default is
    // to always create COLDBOOT_DONE file.
    if (!fn || (act == COLDBOOT_FINISH)) {
        close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000));
    }

    LOG(INFO) << "Coldboot took " << t;
}

void device_close() {
    destroy_platform_devices();
    device_fd.reset();
}

int get_device_fd() {
    return device_fd;
}
+27 −6
Original line number Diff line number Diff line
@@ -17,16 +17,37 @@
#ifndef _INIT_DEVICES_H
#define _INIT_DEVICES_H

#include <functional>
#include <sys/stat.h>

extern void handle_device_fd();
extern void device_init(void);
enum coldboot_action_t {
    // coldboot continues without creating the device for the uevent
    COLDBOOT_CONTINUE = 0,
    // coldboot continues after creating the device for the uevent
    COLDBOOT_CREATE,
    // coldboot stops after creating the device for uevent but doesn't
    // create the COLDBOOT_DONE file
    COLDBOOT_STOP,
    // same as COLDBOOT_STOP, but creates the COLDBOOT_DONE file
    COLDBOOT_FINISH
};

enum early_device_type { EARLY_BLOCK_DEV, EARLY_CHAR_DEV };
struct uevent {
    const char* action;
    const char* path;
    const char* subsystem;
    const char* firmware;
    const char* partition_name;
    const char* device_name;
    int partition_num;
    int major;
    int minor;
};

extern int early_device_socket_open();
extern void early_device_socket_close();
extern void early_create_dev(const std::string& syspath, early_device_type dev_type);
typedef std::function<coldboot_action_t(struct uevent* uevent)> coldboot_callback;
extern coldboot_action_t handle_device_fd(coldboot_callback fn = nullptr);
extern void device_init(const char* path = nullptr, coldboot_callback fn = nullptr);
extern void device_close();

extern int add_dev_perms(const char *name, const char *attr,
                         mode_t perm, unsigned int uid,
+214 −86

File changed.

Preview size limit exceeded, changes collapsed.