mediatek: Introduce create_pl_dev for updating preloader

* Most OEMs who use MediaTek tend to ship preloader images without
  a header, therefore to allow preloader updates, it's necessary to
  create DM devices that allow writing to the physical preloader partition
  without the header.

Change-Id: I6c3168ecabca4d4e56893d2a1bfea6a256577bd0
Signed-off-by: bengris32 <bengris32@protonmail.ch>
This commit is contained in:
bengris32
2024-02-29 20:09:03 +00:00
committed by Matsvei Niaverau
parent d351dce306
commit 6ed9380b91
3 changed files with 165 additions and 0 deletions

18
create_pl_dev/Android.bp Normal file
View File

@@ -0,0 +1,18 @@
//
// SPDX-FileCopyrightText: 2024 The LineageOS Project
// SPDX-License-Identifier: Apache-2.0
//
cc_binary {
name: "create_pl_dev",
srcs: ["create_pl_dev.cpp"],
init_rc: ["create_pl_dev.rc"],
recovery_available: true,
static_libs: [
"libfs_mgr"
],
shared_libs: [
"libbase",
"liblog",
],
}

View File

@@ -0,0 +1,120 @@
/*
* SPDX-FileCopyrightText: 2024 The LineageOS Project
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_TAG "create_pl_dev"
#include <android-base/unique_fd.h>
#include <errno.h>
#include <fcntl.h>
#include <libdm/dm.h>
#include <log/log.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define BLOCK_SIZE 512
#define EMMC_HSZ 0x800
#define UFS_HSZ 0x1000
#define COMBO_HEADER_SIZE 4
#define UFS_HEADER_SIZE 3
#define UFS_HEADER "UFS"
#define EMMC_HEADER "EMMC"
#define COMBO_HEADER "COMB"
using namespace android::dm;
struct pl_device {
const char* dm_name;
const char* dev;
};
static struct pl_device pl_devices[] = {
{"preloader_raw_a", "/dev/block/sda"},
{"preloader_raw_b", "/dev/block/sdb"},
{"preloader_raw_a", "/dev/block/mmcblk0boot0"},
{"preloader_raw_b", "/dev/block/mmcblk0boot1"},
};
static void create_dm_device(const char* name, const char* dev, int start, int count) {
DeviceMapper& dm = DeviceMapper::Instance();
DmTable table;
std::unique_ptr<DmTarget> target;
std::string path;
target = std::make_unique<DmTargetLinear>(0, count, dev, start);
if (!table.AddTarget(std::move(target))) {
ALOGE("Failed to add target for %s.", name);
return;
}
if (!dm.CreateDevice(name, table, &path, std::chrono::milliseconds(500))) {
ALOGE("Failed to create device %s.", name);
return;
}
ALOGI("Created DM device %s at %s.", name, path.c_str());
}
int main() {
int fd, size, count, start;
char header[COMBO_HEADER_SIZE];
for (int i = 0; i < sizeof(pl_devices) / sizeof(pl_device); i++) {
pl_device* device = &pl_devices[i];
if (access(device->dev, F_OK) == -1) {
ALOGE("Device %s not found.", device->dev);
continue;
}
fd = open(device->dev, O_RDONLY);
if (fd == -1) {
ALOGE("Failed to open %s: %s.", device->dev, strerror(errno));
continue;
}
size = lseek(fd, 0, SEEK_END);
if (size == -1) {
ALOGE("Failed to seek %s: %s.", device->dev, strerror(errno));
close(fd);
continue;
}
count = size / BLOCK_SIZE;
if (lseek(fd, 0, SEEK_SET) == -1) {
ALOGE("Failed to seek %s: %s.", device->dev, strerror(errno));
close(fd);
continue;
}
if (read(fd, header, COMBO_HEADER_SIZE) != COMBO_HEADER_SIZE) {
ALOGE("Failed to read %s: %s.", device->dev, strerror(errno));
close(fd);
continue;
}
close(fd);
if (strncmp(header, UFS_HEADER, UFS_HEADER_SIZE) == 0 ||
strncmp(header, COMBO_HEADER, COMBO_HEADER_SIZE) == 0) {
start = UFS_HSZ / BLOCK_SIZE;
} else if (strncmp(header, EMMC_HEADER, COMBO_HEADER_SIZE) == 0) {
start = EMMC_HSZ / BLOCK_SIZE;
} else {
ALOGE("Unknown header %s for %s.", header, device->dev);
continue;
}
count -= start;
create_dm_device(device->dm_name, device->dev, start, count);
}
return 0;
}

View File

@@ -0,0 +1,27 @@
on post-fs
start create_pl_dev
wait /dev/block/mapper/preloader_raw_a
wait /dev/block/mapper/preloader_raw_b
symlink /dev/block/mapper/preloader_raw_a /dev/block/by-name/preloader_raw_a
symlink /dev/block/mapper/preloader_raw_b /dev/block/by-name/preloader_raw_b
symlink /dev/block/mapper/preloader_raw_a /dev/block/platform/bootdevice/by-name/preloader_raw_a
symlink /dev/block/mapper/preloader_raw_b /dev/block/platform/bootdevice/by-name/preloader_raw_b
symlink /dev/block/mapper/preloader_raw_a /dev/block/platform/11270000.ufshci/by-name/preloader_raw_a
symlink /dev/block/mapper/preloader_raw_b /dev/block/platform/11270000.ufshci/by-name/preloader_raw_b
symlink /dev/block/mapper/preloader_raw_a /dev/block/platform/11230000.mmc/by-name/preloader_raw_a
symlink /dev/block/mapper/preloader_raw_b /dev/block/platform/11230000.mmc/by-name/preloader_raw_b
symlink /dev/block/mapper/preloader_raw_a /dev/block/platform/11230000.msdc/by-name/preloader_raw_a
symlink /dev/block/mapper/preloader_raw_b /dev/block/platform/11230000.msdc/by-name/preloader_raw_b
service create_pl_dev /system/bin/create_pl_dev
user root
group root
seclabel u:r:update_engine:s0
oneshot
disabled