mirror of
https://github.com/linux-msm/qbootctl
synced 2024-11-23 14:43:29 +08:00
Use scope-based memory management for malloc, free, open, close, etc.
If we are using C++, we might as well use scope-based memory management for these things, cleaner and less error prone. Also removed unnecessary gotos.
This commit is contained in:
parent
843aa92266
commit
9d7600df51
@ -68,26 +68,42 @@ enum part_attr_type {
|
||||
ATTR_BOOTABLE,
|
||||
};
|
||||
|
||||
struct file {
|
||||
int fd = -1;
|
||||
|
||||
~file()
|
||||
{
|
||||
if (fd > -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int open(const char *path)
|
||||
{
|
||||
fd = ::open(path, O_RDONLY);
|
||||
return fd;
|
||||
}
|
||||
};
|
||||
|
||||
void get_kernel_cmdline_arg(const char *arg, char *buf, const char *def)
|
||||
{
|
||||
int fd;
|
||||
file file;
|
||||
char pcmd[MAX_CMDLINE_SIZE];
|
||||
char *val, *found, *ptr = buf;
|
||||
fd = open("/proc/cmdline", O_RDONLY);
|
||||
int rc = read(fd, pcmd, MAX_CMDLINE_SIZE);
|
||||
file.open("/proc/cmdline");
|
||||
int rc = read(file.fd, pcmd, MAX_CMDLINE_SIZE);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Couldn't open /proc/cmdline: %d (%s)\n", rc,
|
||||
strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
found = strstr(pcmd, arg);
|
||||
if (!found || !(val = strstr(found, "="))) {
|
||||
fprintf(stderr, "Couldn't find cmdline arg: '%s'\n", arg);
|
||||
goto error;
|
||||
}
|
||||
|
||||
val++;
|
||||
++val;
|
||||
// no this doesn't handle quotes lol
|
||||
while (*val != ' ') {
|
||||
*ptr++ = *val++;
|
||||
@ -103,28 +119,25 @@ error:
|
||||
static int get_partition_attribute(char *partname,
|
||||
enum part_attr_type part_attr)
|
||||
{
|
||||
struct gpt_disk *disk = NULL;
|
||||
struct gpt_disk disk;
|
||||
uint8_t *pentry = NULL;
|
||||
int retval = -1;
|
||||
uint8_t *attr = NULL;
|
||||
if (!partname)
|
||||
goto error;
|
||||
disk = gpt_disk_alloc();
|
||||
if (!disk) {
|
||||
fprintf(stderr, "%s: Failed to alloc disk struct\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
if (gpt_disk_get_disk_info(partname, disk)) {
|
||||
fprintf(stderr, "%s: Failed to get disk info\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
pentry = gpt_disk_get_pentry(disk, partname, PRIMARY_GPT);
|
||||
return retval;
|
||||
|
||||
if (gpt_disk_get_disk_info(partname, &disk)) {
|
||||
fprintf(stderr, "%s: Failed to get disk info\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
pentry = gpt_disk_get_pentry(&disk, partname, PRIMARY_GPT);
|
||||
if (!pentry) {
|
||||
fprintf(stderr, "%s: pentry does not exist in disk struct\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return retval;
|
||||
}
|
||||
|
||||
attr = pentry + AB_FLAG_OFFSET;
|
||||
LOGD("get_partition_attribute() partname = %s, attr = 0x%x\n", partname,
|
||||
*attr);
|
||||
@ -138,14 +151,8 @@ static int get_partition_attribute(char *partname,
|
||||
} else if (part_attr == ATTR_UNBOOTABLE) {
|
||||
retval = !!(*attr & AB_PARTITION_ATTR_UNBOOTABLE);
|
||||
LOGD("AB_PARTITION_ATTR_UNBOOTABLE, retval = %d\n", retval);
|
||||
} else {
|
||||
retval = -1;
|
||||
}
|
||||
gpt_disk_free(disk);
|
||||
return retval;
|
||||
error:
|
||||
if (disk)
|
||||
gpt_disk_free(disk);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -156,7 +163,7 @@ static int update_slot_attribute(const char *slot, enum part_attr_type ab_attr)
|
||||
unsigned int i = 0;
|
||||
char buf[PATH_MAX];
|
||||
struct stat st;
|
||||
struct gpt_disk *disk = NULL;
|
||||
struct gpt_disk disk;
|
||||
uint8_t *pentry = NULL;
|
||||
uint8_t *pentry_bak = NULL;
|
||||
int rc = -1;
|
||||
@ -167,17 +174,20 @@ static int update_slot_attribute(const char *slot, enum part_attr_type ab_attr)
|
||||
int slot_name_valid = 0;
|
||||
if (!slot) {
|
||||
fprintf(stderr, "%s: Invalid argument\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; slot_suffix_arr[i] != NULL; i++) {
|
||||
if (!strncmp(slot, slot_suffix_arr[i],
|
||||
strlen(slot_suffix_arr[i])))
|
||||
slot_name_valid = 1;
|
||||
}
|
||||
|
||||
if (!slot_name_valid) {
|
||||
fprintf(stderr, "%s: Invalid slot name\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ptn_list); i++) {
|
||||
memset(buf, '\0', sizeof(buf));
|
||||
//Check if A/B versions of this ptn exist
|
||||
@ -197,26 +207,23 @@ static int update_slot_attribute(const char *slot, enum part_attr_type ab_attr)
|
||||
memset(partName, '\0', sizeof(partName));
|
||||
snprintf(partName, sizeof(partName) - 1, "%s%s", ptn_list[i],
|
||||
slot);
|
||||
disk = gpt_disk_alloc();
|
||||
if (!disk) {
|
||||
fprintf(stderr, "%s: Failed to alloc disk struct\n",
|
||||
__func__);
|
||||
goto error;
|
||||
}
|
||||
rc = gpt_disk_get_disk_info(partName, disk);
|
||||
rc = gpt_disk_get_disk_info(partName, &disk);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "%s: Failed to get disk info for %s\n",
|
||||
__func__, partName);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
pentry = gpt_disk_get_pentry(disk, partName, PRIMARY_GPT);
|
||||
pentry_bak = gpt_disk_get_pentry(disk, partName, SECONDARY_GPT);
|
||||
|
||||
pentry = gpt_disk_get_pentry(&disk, partName, PRIMARY_GPT);
|
||||
pentry_bak =
|
||||
gpt_disk_get_pentry(&disk, partName, SECONDARY_GPT);
|
||||
if (!pentry || !pentry_bak) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to get pentry/pentry_bak for %s\n",
|
||||
__func__, partName);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
attr = pentry + AB_FLAG_OFFSET;
|
||||
LOGD("%s: got pentry for part '%s': 0x%lx (at flags: 0x%x)\n",
|
||||
__func__, partName, *(uint64_t *)pentry, *attr);
|
||||
@ -241,42 +248,55 @@ static int update_slot_attribute(const char *slot, enum part_attr_type ab_attr)
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: Unrecognized attr\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
if (gpt_disk_update_crc(disk)) {
|
||||
|
||||
if (gpt_disk_update_crc(&disk)) {
|
||||
fprintf(stderr, "%s: Failed to update crc for %s\n",
|
||||
__func__, partName);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
if (gpt_disk_commit(disk)) {
|
||||
|
||||
if (gpt_disk_commit(&disk)) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to write back entry for %s\n",
|
||||
__func__, partName);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
gpt_disk_free(disk);
|
||||
disk = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (disk)
|
||||
gpt_disk_free(disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct dir {
|
||||
DIR *dir = NULL;
|
||||
|
||||
~dir()
|
||||
{
|
||||
if (dir)
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
DIR *open(const char *name)
|
||||
{
|
||||
dir = opendir(name);
|
||||
return dir;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned get_number_slots()
|
||||
{
|
||||
struct dirent *de = NULL;
|
||||
DIR *dir_bootdev = NULL;
|
||||
dir dir_bootdev;
|
||||
unsigned slot_count = 0;
|
||||
|
||||
dir_bootdev = opendir(BOOTDEV_DIR);
|
||||
if (!dir_bootdev) {
|
||||
if (!dir_bootdev.open(BOOTDEV_DIR)) {
|
||||
fprintf(stderr, "%s: Failed to open bootdev dir (%s)\n",
|
||||
__func__, strerror(errno));
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
while ((de = readdir(dir_bootdev))) {
|
||||
|
||||
while ((de = readdir(dir_bootdev.dir))) {
|
||||
if (de->d_name[0] == '.')
|
||||
continue;
|
||||
static_assert(AB_SLOT_A_SUFFIX[0] == '_',
|
||||
@ -290,12 +310,8 @@ unsigned get_number_slots()
|
||||
slot_count++;
|
||||
}
|
||||
}
|
||||
closedir(dir_bootdev);
|
||||
|
||||
return slot_count;
|
||||
error:
|
||||
if (dir_bootdev)
|
||||
closedir(dir_bootdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int get_current_slot()
|
||||
@ -308,12 +324,14 @@ static unsigned int get_current_slot()
|
||||
//Slot 0 is the only slot around.
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_kernel_cmdline_arg(BOOT_SLOT_PROP, bootSlotProp, "_a");
|
||||
if (!strncmp(bootSlotProp, "N/A\n", strlen("N/A"))) {
|
||||
fprintf(stderr, "%s: Unable to read boot slot property\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Iterate through a list of partitons named as boot+suffix
|
||||
//and see which one is currently active.
|
||||
for (i = 0; slot_suffix_arr[i] != NULL; i++) {
|
||||
@ -323,7 +341,7 @@ static unsigned int get_current_slot()
|
||||
return i;
|
||||
}
|
||||
}
|
||||
error:
|
||||
|
||||
//The HAL spec requires that we return a number between
|
||||
//0 to num_slots - 1. Since something went wrong here we
|
||||
//are just going to return the default slot.
|
||||
@ -383,13 +401,12 @@ int mark_boot_successful(unsigned slot)
|
||||
|
||||
if (update_slot_attribute(slot_suffix_arr[slot],
|
||||
ATTR_BOOT_SUCCESSFUL)) {
|
||||
goto error;
|
||||
fprintf(stderr, "SLOT %s: Failed to mark boot successful\n",
|
||||
slot_suffix_arr[slot]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
fprintf(stderr, "SLOT %s: Failed to mark boot successful\n",
|
||||
slot_suffix_arr[slot]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *get_suffix(unsigned slot)
|
||||
@ -402,25 +419,17 @@ const char *get_suffix(unsigned slot)
|
||||
|
||||
//Return a gpt disk structure representing the disk that holds
|
||||
//partition.
|
||||
static struct gpt_disk *boot_ctl_get_disk_info(char *partition)
|
||||
static bool boot_ctl_get_disk_info(char *partition, gpt_disk *disk)
|
||||
{
|
||||
struct gpt_disk *disk = NULL;
|
||||
if (!partition)
|
||||
return NULL;
|
||||
disk = gpt_disk_alloc();
|
||||
if (!disk) {
|
||||
fprintf(stderr, "%s: Failed to alloc disk\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
return false;
|
||||
|
||||
if (gpt_disk_get_disk_info(partition, disk)) {
|
||||
fprintf(stderr, "failed to get disk info for %s\n", partition);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
return disk;
|
||||
error:
|
||||
if (disk)
|
||||
gpt_disk_free(disk);
|
||||
return NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//The argument here is a vector of partition names(including the slot suffix)
|
||||
@ -429,7 +438,7 @@ static int boot_ctl_set_active_slot_for_partitions(vector<string> part_list,
|
||||
unsigned slot)
|
||||
{
|
||||
char buf[PATH_MAX] = { 0 };
|
||||
struct gpt_disk *disk = NULL;
|
||||
struct gpt_disk disk;
|
||||
char slotA[MAX_GPT_NAME_SIZE + 1] = { 0 };
|
||||
char slotB[MAX_GPT_NAME_SIZE + 1] = { 0 };
|
||||
char active_guid[TYPE_GUID_SIZE + 1] = { 0 };
|
||||
@ -455,8 +464,9 @@ static int boot_ctl_set_active_slot_for_partitions(vector<string> part_list,
|
||||
if (prefix.size() < (strlen(AB_SLOT_A_SUFFIX) + 1)) {
|
||||
fprintf(stderr, "Invalid partition name: %s\n",
|
||||
prefix.c_str());
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
prefix.resize(prefix.size() - strlen(AB_SLOT_A_SUFFIX));
|
||||
//Check if A/B versions of this ptn exist
|
||||
snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR,
|
||||
@ -484,26 +494,26 @@ static int boot_ctl_set_active_slot_for_partitions(vector<string> part_list,
|
||||
AB_SLOT_A_SUFFIX);
|
||||
snprintf(slotB, sizeof(slotB) - 1, "%s%s", prefix.c_str(),
|
||||
AB_SLOT_B_SUFFIX);
|
||||
|
||||
//Get the disk containing the partitions that were passed in.
|
||||
//All partitions passed in must lie on the same disk.
|
||||
if (!disk) {
|
||||
disk = boot_ctl_get_disk_info(slotA);
|
||||
if (!disk)
|
||||
goto error;
|
||||
}
|
||||
if (!boot_ctl_get_disk_info(slotA, &disk))
|
||||
return -1;
|
||||
|
||||
//Get partition entry for slot A & B from the primary
|
||||
//and backup tables.
|
||||
pentryA = gpt_disk_get_pentry(disk, slotA, PRIMARY_GPT);
|
||||
pentryA_bak = gpt_disk_get_pentry(disk, slotA, SECONDARY_GPT);
|
||||
pentryB = gpt_disk_get_pentry(disk, slotB, PRIMARY_GPT);
|
||||
pentryB_bak = gpt_disk_get_pentry(disk, slotB, SECONDARY_GPT);
|
||||
pentryA = gpt_disk_get_pentry(&disk, slotA, PRIMARY_GPT);
|
||||
pentryA_bak = gpt_disk_get_pentry(&disk, slotA, SECONDARY_GPT);
|
||||
pentryB = gpt_disk_get_pentry(&disk, slotB, PRIMARY_GPT);
|
||||
pentryB_bak = gpt_disk_get_pentry(&disk, slotB, SECONDARY_GPT);
|
||||
if (!pentryA || !pentryA_bak || !pentryB || !pentryB_bak) {
|
||||
//None of these should be NULL since we have already
|
||||
//checked for A & B versions earlier.
|
||||
fprintf(stderr, "Slot pentries for %s not found.\n",
|
||||
prefix.c_str());
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("\tAB attr (A): 0x%x (backup: 0x%x)\n",
|
||||
*(uint16_t *)(pentryA + AB_FLAG_OFFSET),
|
||||
*(uint16_t *)(pentryA_bak + AB_FLAG_OFFSET));
|
||||
@ -527,8 +537,9 @@ static int boot_ctl_set_active_slot_for_partitions(vector<string> part_list,
|
||||
TYPE_GUID_SIZE);
|
||||
} else {
|
||||
fprintf(stderr, "Both A & B are inactive..Aborting");
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// printf("\tActive GUID: %s\n", active_guid);
|
||||
// printf("\tInactive GUID: %s\n", active_guid);
|
||||
if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX,
|
||||
@ -554,28 +565,23 @@ static int boot_ctl_set_active_slot_for_partitions(vector<string> part_list,
|
||||
} else {
|
||||
//Something has gone terribly terribly wrong
|
||||
fprintf(stderr, "%s: Unknown slot suffix!\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
if (gpt_disk_update_crc(disk) != 0) {
|
||||
|
||||
if (gpt_disk_update_crc(&disk) != 0) {
|
||||
fprintf(stderr, "%s: Failed to update gpt_disk crc\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//write updated content to disk
|
||||
if (disk) {
|
||||
if (gpt_disk_commit(disk)) {
|
||||
fprintf(stderr, "Failed to commit disk entry");
|
||||
goto error;
|
||||
}
|
||||
gpt_disk_free(disk);
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (disk)
|
||||
gpt_disk_free(disk);
|
||||
return -1;
|
||||
//write updated content to disk
|
||||
if (gpt_disk_commit(&disk)) {
|
||||
fprintf(stderr, "Failed to commit disk entry");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned get_active_boot_slot()
|
||||
@ -607,13 +613,13 @@ int set_active_boot_slot(unsigned slot)
|
||||
|
||||
if (boot_control_check_slot_sanity(slot)) {
|
||||
fprintf(stderr, "%s: Bad arguments\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ismmc = gpt_utils_is_partition_backed_by_emmc(PTN_XBL AB_SLOT_A_SUFFIX);
|
||||
|
||||
if (!ismmc && ufs_bsg_dev_open() < 0) {
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//The partition list just contains prefixes(without the _a/_b) of the
|
||||
@ -629,6 +635,7 @@ int set_active_boot_slot(unsigned slot)
|
||||
cur_ptn.append(AB_SLOT_A_SUFFIX);
|
||||
ptn_vec.push_back(cur_ptn);
|
||||
}
|
||||
|
||||
//The partition map gives us info in the following format:
|
||||
// [path_to_block_device_1]--><partitions on device 1>
|
||||
// [path_to_block_device_2]--><partitions on device 2>
|
||||
@ -638,8 +645,9 @@ int set_active_boot_slot(unsigned slot)
|
||||
// [/dev/block/sdb]---><system, boot, rpm, tz,....>
|
||||
if (gpt_utils_get_partition_map(ptn_vec, ptn_map)) {
|
||||
fprintf(stderr, "%s: Failed to get partition map\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (map_iter = ptn_map.begin(); map_iter != ptn_map.end();
|
||||
map_iter++) {
|
||||
if (map_iter->second.size() < 1)
|
||||
@ -649,8 +657,7 @@ int set_active_boot_slot(unsigned slot)
|
||||
fprintf(stderr,
|
||||
"%s: Failed to set active slot for partitions \n",
|
||||
__func__);
|
||||
;
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -669,19 +676,17 @@ int set_active_boot_slot(unsigned slot)
|
||||
} else {
|
||||
//Something has gone terribly terribly wrong
|
||||
fprintf(stderr, "%s: Unknown slot suffix!\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to switch xbl boot partition\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int set_slot_as_unbootable(unsigned slot)
|
||||
@ -706,15 +711,16 @@ int is_slot_marked_successful(unsigned slot)
|
||||
|
||||
if (boot_control_check_slot_sanity(slot) != 0) {
|
||||
fprintf(stderr, "%s: Argument check failed\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(bootPartition, sizeof(bootPartition) - 1, "boot%s",
|
||||
slot_suffix_arr[slot]);
|
||||
attr = get_partition_attribute(bootPartition, ATTR_BOOT_SUCCESSFUL);
|
||||
LOGD("%s: slot = %d, attr = 0x%x\n", __func__, slot, attr);
|
||||
if (attr >= 0)
|
||||
return attr;
|
||||
error:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
329
gpt-utils.cpp
329
gpt-utils.cpp
@ -272,7 +272,7 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
|
||||
else {
|
||||
fprintf(stderr, "%s: Failed to locate secondary xbl\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
} else if (chain == NORMAL_BOOT) {
|
||||
boot_lun_id = BOOT_LUN_A_ID;
|
||||
@ -283,28 +283,28 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
|
||||
else {
|
||||
fprintf(stderr, "%s: Failed to locate primary xbl\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s: Invalid boot chain id\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//We need either both xbl and xblbak or both xbl_a and xbl_b to exist at
|
||||
//the same time. If not the current configuration is invalid.
|
||||
if ((stat(XBL_PRIMARY, &st) || stat(XBL_BACKUP, &st)) &&
|
||||
(stat(XBL_AB_PRIMARY, &st) || stat(XBL_AB_SECONDARY, &st))) {
|
||||
fprintf(stderr, "%s:primary/secondary XBL prt not found(%s)\n",
|
||||
__func__, strerror(errno));
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("%s: setting %s lun as boot lun\n", __func__, boot_dev);
|
||||
|
||||
if (set_boot_lun(boot_lun_id)) {
|
||||
goto error;
|
||||
}
|
||||
if (set_boot_lun(boot_lun_id))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Given a parttion name(eg: rpm) get the path to the block device that
|
||||
@ -387,16 +387,16 @@ static uint32_t gpt_get_block_size(int fd)
|
||||
uint32_t block_size = 0;
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: invalid descriptor\n", __func__);
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl(fd, BLKSSZGET, &block_size) != 0) {
|
||||
fprintf(stderr, "%s: Failed to get GPT dev block size : %s\n",
|
||||
__func__, strerror(errno));
|
||||
goto error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return block_size;
|
||||
error:
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Write the GPT header present in the passed in buffer back to the
|
||||
@ -408,146 +408,150 @@ static int gpt_set_header(uint8_t *gpt_header, int fd,
|
||||
off_t gpt_header_offset = 0;
|
||||
if (!gpt_header || fd < 0) {
|
||||
fprintf(stderr, "%s: Invalid arguments\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
block_size = gpt_get_block_size(fd);
|
||||
LOGD("%s: Block size is : %d\n", __func__, block_size);
|
||||
if (block_size == 0) {
|
||||
fprintf(stderr, "%s: Failed to get block size\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (instance == PRIMARY_GPT)
|
||||
gpt_header_offset = block_size;
|
||||
else
|
||||
gpt_header_offset = lseek64(fd, 0, SEEK_END) - block_size;
|
||||
|
||||
if (gpt_header_offset <= 0) {
|
||||
fprintf(stderr, "%s: Failed to get gpt header offset\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("%s: Writing back header to offset %ld\n", __func__,
|
||||
gpt_header_offset);
|
||||
if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) {
|
||||
fprintf(stderr, "%s: Failed to write back GPT header\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct file {
|
||||
int fd = -1;
|
||||
|
||||
~file()
|
||||
{
|
||||
if (fd > -1) {
|
||||
fsync(fd);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int open(const char *path)
|
||||
{
|
||||
fd = ::open(path, O_RDWR);
|
||||
return fd;
|
||||
}
|
||||
};
|
||||
|
||||
//Read out the GPT header for the disk that contains the partition partname
|
||||
static uint8_t *gpt_get_header(const char *partname, enum gpt_instance instance)
|
||||
static bool gpt_get_header(const char *partname, enum gpt_instance instance,
|
||||
std::vector<uint8_t> *hdr)
|
||||
{
|
||||
uint8_t *hdr = NULL;
|
||||
char devpath[PATH_MAX] = { 0 };
|
||||
off_t hdr_offset = 0;
|
||||
uint32_t block_size = 0;
|
||||
int fd = -1;
|
||||
file file;
|
||||
if (!partname) {
|
||||
fprintf(stderr, "%s: Invalid partition name\n", __func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (get_dev_path_from_partition_name(partname, devpath,
|
||||
sizeof(devpath)) != 0) {
|
||||
fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__,
|
||||
partname);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
fd = open(devpath, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: Failed to open %s : %s\n", __func__,
|
||||
|
||||
if (file.open(devpath) < 0) {
|
||||
fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
|
||||
devpath, strerror(errno));
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
block_size = gpt_get_block_size(fd);
|
||||
|
||||
block_size = gpt_get_block_size(file.fd);
|
||||
if (block_size == 0) {
|
||||
fprintf(stderr, "%s: Failed to get gpt block size for %s\n",
|
||||
__func__, partname);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
hdr = (uint8_t *)calloc(block_size, 1);
|
||||
if (!hdr) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to allocate memory for gpt header\n",
|
||||
__func__);
|
||||
}
|
||||
hdr->resize(block_size);
|
||||
std::fill(hdr->begin(), hdr->end(), 0);
|
||||
if (instance == PRIMARY_GPT)
|
||||
hdr_offset = block_size;
|
||||
else {
|
||||
hdr_offset = lseek64(fd, 0, SEEK_END) - block_size;
|
||||
}
|
||||
else
|
||||
hdr_offset = lseek64(file.fd, 0, SEEK_END) - block_size;
|
||||
|
||||
if (hdr_offset < 0) {
|
||||
fprintf(stderr, "%s: Failed to get gpt header offset\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
if (blk_rw(fd, 0, hdr_offset, hdr, block_size)) {
|
||||
|
||||
if (blk_rw(file.fd, 0, hdr_offset, hdr->data(), block_size)) {
|
||||
fprintf(stderr, "%s: Failed to read GPT header from device\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
//DumpHex(hdr, block_size);
|
||||
close(fd);
|
||||
return hdr;
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
if (hdr)
|
||||
free(hdr);
|
||||
return NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Returns the partition entry array based on the
|
||||
//passed in buffer which contains the gpt header.
|
||||
//The fd here is the descriptor for the 'disk' which
|
||||
//holds the partition
|
||||
static uint8_t *gpt_get_pentry_arr(uint8_t *hdr, int fd)
|
||||
static bool gpt_get_pentry_arr(uint8_t *hdr, int fd,
|
||||
std::vector<uint8_t> *pentry_arr)
|
||||
{
|
||||
uint64_t pentries_start = 0;
|
||||
uint32_t pentry_size = 0;
|
||||
uint32_t block_size = 0;
|
||||
uint32_t pentries_arr_size = 0;
|
||||
uint8_t *pentry_arr = NULL;
|
||||
int rc = 0;
|
||||
if (!hdr) {
|
||||
fprintf(stderr, "%s: Invalid header\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "%s: Invalid fd\n", __func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
block_size = gpt_get_block_size(fd);
|
||||
if (!block_size) {
|
||||
fprintf(stderr, "%s: Failed to get gpt block size for\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
|
||||
pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
|
||||
pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
|
||||
pentries_arr_size =
|
||||
GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
|
||||
pentry_arr = (uint8_t *)calloc(1, pentries_arr_size);
|
||||
if (!pentry_arr) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to allocate memory for partition array\n",
|
||||
__func__);
|
||||
goto error;
|
||||
}
|
||||
rc = blk_rw(fd, 0, pentries_start, pentry_arr, pentries_arr_size);
|
||||
pentry_arr->resize(pentries_arr_size);
|
||||
std::fill(pentry_arr->begin(), pentry_arr->end(), 0);
|
||||
rc = blk_rw(fd, 0, pentries_start, pentry_arr->data(),
|
||||
pentries_arr_size);
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: Failed to read partition entry array\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return false;
|
||||
}
|
||||
return pentry_arr;
|
||||
error:
|
||||
if (pentry_arr)
|
||||
free(pentry_arr);
|
||||
return NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t *arr)
|
||||
@ -559,14 +563,16 @@ static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t *arr)
|
||||
int rc = 0;
|
||||
if (!hdr || fd < 0 || !arr) {
|
||||
fprintf(stderr, "%s: Invalid argument\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
block_size = gpt_get_block_size(fd);
|
||||
if (!block_size) {
|
||||
fprintf(stderr, "%s: Failed to get gpt block size for\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("%s : Block size is %d\n", __func__, block_size);
|
||||
pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
|
||||
pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
|
||||
@ -580,71 +586,40 @@ static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t *arr)
|
||||
if (rc) {
|
||||
fprintf(stderr, "%s: Failed to read partition entry array\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Allocate a handle used by calls to the "gpt_disk" api's
|
||||
struct gpt_disk *gpt_disk_alloc()
|
||||
{
|
||||
struct gpt_disk *disk;
|
||||
disk = (struct gpt_disk *)malloc(sizeof(struct gpt_disk));
|
||||
if (!disk) {
|
||||
fprintf(stderr, "%s: Failed to allocate memory\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
memset(disk, 0, sizeof(struct gpt_disk));
|
||||
end:
|
||||
return disk;
|
||||
}
|
||||
|
||||
//Free previously allocated/initialized handle
|
||||
void gpt_disk_free(struct gpt_disk *disk)
|
||||
{
|
||||
if (!disk)
|
||||
return;
|
||||
if (disk->hdr)
|
||||
free(disk->hdr);
|
||||
if (disk->hdr_bak)
|
||||
free(disk->hdr_bak);
|
||||
if (disk->pentry_arr)
|
||||
free(disk->pentry_arr);
|
||||
if (disk->pentry_arr_bak)
|
||||
free(disk->pentry_arr_bak);
|
||||
free(disk);
|
||||
return;
|
||||
}
|
||||
|
||||
//fills up the passed in gpt_disk struct with information about the
|
||||
//disk represented by path dev. Returns 0 on success and -1 on error.
|
||||
int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *dsk)
|
||||
int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk)
|
||||
{
|
||||
struct gpt_disk *disk = NULL;
|
||||
int fd = -1;
|
||||
file file;
|
||||
uint32_t gpt_header_size = 0;
|
||||
|
||||
if (!dsk || !dev) {
|
||||
if (!disk || !dev) {
|
||||
fprintf(stderr, "%s: Invalid arguments\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
disk = dsk;
|
||||
disk->hdr = gpt_get_header(dev, PRIMARY_GPT);
|
||||
if (!disk->hdr) {
|
||||
|
||||
gpt_get_header(dev, PRIMARY_GPT, &disk->hdr);
|
||||
if (disk->hdr.empty()) {
|
||||
fprintf(stderr, "%s: Failed to get primary header\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
|
||||
|
||||
gpt_header_size = GET_4_BYTES(disk->hdr.data() + HEADER_SIZE_OFFSET);
|
||||
// FIXME: pointer offsets crc bleh
|
||||
disk->hdr_crc = crc32(0, disk->hdr, gpt_header_size);
|
||||
disk->hdr_bak = gpt_get_header(dev, PRIMARY_GPT);
|
||||
if (!disk->hdr_bak) {
|
||||
disk->hdr_crc = crc32(0, disk->hdr.data(), gpt_header_size);
|
||||
gpt_get_header(dev, PRIMARY_GPT, &disk->hdr_bak);
|
||||
if (disk->hdr_bak.empty()) {
|
||||
fprintf(stderr, "%s: Failed to get backup header\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
disk->hdr_bak_crc = crc32(0, disk->hdr_bak, gpt_header_size);
|
||||
|
||||
disk->hdr_bak_crc = crc32(0, disk->hdr_bak.data(), gpt_header_size);
|
||||
|
||||
//Descriptor for the block device. We will use this for further
|
||||
//modifications to the partition table
|
||||
@ -652,42 +627,42 @@ int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *dsk)
|
||||
sizeof(disk->devpath)) != 0) {
|
||||
fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__,
|
||||
dev);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
fd = open(disk->devpath, O_RDWR);
|
||||
if (fd < 0) {
|
||||
|
||||
if (file.open(disk->devpath) < 0) {
|
||||
fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
|
||||
disk->devpath, strerror(errno));
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
disk->pentry_arr = gpt_get_pentry_arr(disk->hdr, fd);
|
||||
if (!disk->pentry_arr) {
|
||||
|
||||
gpt_get_pentry_arr(disk->hdr.data(), file.fd, &disk->pentry_arr);
|
||||
if (disk->pentry_arr.empty()) {
|
||||
fprintf(stderr, "%s: Failed to obtain partition entry array\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
disk->pentry_arr_bak = gpt_get_pentry_arr(disk->hdr_bak, fd);
|
||||
if (!disk->pentry_arr_bak) {
|
||||
|
||||
gpt_get_pentry_arr(disk->hdr_bak.data(), file.fd,
|
||||
&disk->pentry_arr_bak);
|
||||
if (disk->pentry_arr_bak.empty()) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to obtain backup partition entry array\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
disk->pentry_size = GET_4_BYTES(disk->hdr + PENTRY_SIZE_OFFSET);
|
||||
|
||||
disk->pentry_size = GET_4_BYTES(disk->hdr.data() + PENTRY_SIZE_OFFSET);
|
||||
disk->pentry_arr_size =
|
||||
GET_4_BYTES(disk->hdr + PARTITION_COUNT_OFFSET) *
|
||||
GET_4_BYTES(disk->hdr.data() + PARTITION_COUNT_OFFSET) *
|
||||
disk->pentry_size;
|
||||
disk->pentry_arr_crc = GET_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET);
|
||||
disk->pentry_arr_crc =
|
||||
GET_4_BYTES(disk->hdr.data() + PARTITION_CRC_OFFSET);
|
||||
disk->pentry_arr_bak_crc =
|
||||
GET_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET);
|
||||
disk->block_size = gpt_get_block_size(fd);
|
||||
close(fd);
|
||||
GET_4_BYTES(disk->hdr_bak.data() + PARTITION_CRC_OFFSET);
|
||||
disk->block_size = gpt_get_block_size(file.fd);
|
||||
disk->is_initialized = GPT_DISK_INIT_MAGIC;
|
||||
return 0;
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Get pointer to partition entry from a allocated gpt_disk structure
|
||||
@ -697,15 +672,14 @@ uint8_t *gpt_disk_get_pentry(struct gpt_disk *disk, const char *partname,
|
||||
uint8_t *ptn_arr = NULL;
|
||||
if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) {
|
||||
fprintf(stderr, "%s: Invalid argument\n", __func__);
|
||||
goto error;
|
||||
return NULL;
|
||||
}
|
||||
ptn_arr = (instance == PRIMARY_GPT) ? disk->pentry_arr :
|
||||
disk->pentry_arr_bak;
|
||||
|
||||
ptn_arr = (instance == PRIMARY_GPT) ? disk->pentry_arr.data() :
|
||||
disk->pentry_arr_bak.data();
|
||||
return (gpt_pentry_seek(partname, ptn_arr,
|
||||
ptn_arr + disk->pentry_arr_size,
|
||||
disk->pentry_size));
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Update CRC values for the various components of the gpt_disk
|
||||
@ -717,69 +691,68 @@ int gpt_disk_update_crc(struct gpt_disk *disk)
|
||||
uint32_t gpt_header_size = 0;
|
||||
if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
|
||||
fprintf(stderr, "%s: invalid argument\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Recalculate the CRC of the primary partiton array
|
||||
disk->pentry_arr_crc =
|
||||
crc32(0, disk->pentry_arr, disk->pentry_arr_size);
|
||||
crc32(0, disk->pentry_arr.data(), disk->pentry_arr_size);
|
||||
//Recalculate the CRC of the backup partition array
|
||||
disk->pentry_arr_bak_crc =
|
||||
crc32(0, disk->pentry_arr_bak, disk->pentry_arr_size);
|
||||
crc32(0, disk->pentry_arr_bak.data(), disk->pentry_arr_size);
|
||||
//Update the partition CRC value in the primary GPT header
|
||||
PUT_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET, disk->pentry_arr_crc);
|
||||
PUT_4_BYTES(disk->hdr.data() + PARTITION_CRC_OFFSET,
|
||||
disk->pentry_arr_crc);
|
||||
//Update the partition CRC value in the backup GPT header
|
||||
PUT_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET,
|
||||
PUT_4_BYTES(disk->hdr_bak.data() + PARTITION_CRC_OFFSET,
|
||||
disk->pentry_arr_bak_crc);
|
||||
//Update the CRC value of the primary header
|
||||
gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
|
||||
gpt_header_size = GET_4_BYTES(disk->hdr.data() + HEADER_SIZE_OFFSET);
|
||||
//Header CRC is calculated with its own CRC field set to 0
|
||||
PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, 0);
|
||||
PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, 0);
|
||||
disk->hdr_crc = crc32(0, disk->hdr, gpt_header_size);
|
||||
disk->hdr_bak_crc = crc32(0, disk->hdr_bak, gpt_header_size);
|
||||
PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, disk->hdr_crc);
|
||||
PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, disk->hdr_bak_crc);
|
||||
PUT_4_BYTES(disk->hdr.data() + HEADER_CRC_OFFSET, 0);
|
||||
PUT_4_BYTES(disk->hdr_bak.data() + HEADER_CRC_OFFSET, 0);
|
||||
disk->hdr_crc = crc32(0, disk->hdr.data(), gpt_header_size);
|
||||
disk->hdr_bak_crc = crc32(0, disk->hdr_bak.data(), gpt_header_size);
|
||||
PUT_4_BYTES(disk->hdr.data() + HEADER_CRC_OFFSET, disk->hdr_crc);
|
||||
PUT_4_BYTES(disk->hdr_bak.data() + HEADER_CRC_OFFSET,
|
||||
disk->hdr_bak_crc);
|
||||
return 0;
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Write the contents of struct gpt_disk back to the actual disk
|
||||
int gpt_disk_commit(struct gpt_disk *disk)
|
||||
{
|
||||
int fd = -1;
|
||||
file file;
|
||||
if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
|
||||
fprintf(stderr, "%s: Invalid args\n", __func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
fd = open(disk->devpath, O_RDWR);
|
||||
if (fd < 0) {
|
||||
|
||||
if (file.open(disk->devpath) < 0) {
|
||||
fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
|
||||
disk->devpath, strerror(errno));
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("%s: Writing back primary GPT header\n", __func__);
|
||||
//Write the primary header
|
||||
if (gpt_set_header(disk->hdr, fd, PRIMARY_GPT) != 0) {
|
||||
if (gpt_set_header(disk->hdr.data(), file.fd, PRIMARY_GPT) != 0) {
|
||||
fprintf(stderr, "%s: Failed to update primary GPT header\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOGD("%s: Writing back primary partition array\n", __func__);
|
||||
//Write back the primary partition array
|
||||
if (gpt_set_pentry_arr(disk->hdr, fd, disk->pentry_arr)) {
|
||||
if (gpt_set_pentry_arr(disk->hdr.data(), file.fd,
|
||||
disk->pentry_arr.data())) {
|
||||
fprintf(stderr,
|
||||
"%s: Failed to write primary GPT partition arr\n",
|
||||
__func__);
|
||||
goto error;
|
||||
return -1;
|
||||
}
|
||||
fsync(fd);
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Determine whether to handle the given partition as eMMC or UFS, using the
|
||||
|
30
gpt-utils.h
30
gpt-utils.h
@ -96,36 +96,32 @@ enum boot_chain { NORMAL_BOOT = 0, BACKUP_BOOT };
|
||||
|
||||
struct gpt_disk {
|
||||
//GPT primary header
|
||||
uint8_t *hdr;
|
||||
std::vector<uint8_t> hdr;
|
||||
//primary header crc
|
||||
uint32_t hdr_crc;
|
||||
uint32_t hdr_crc = 0;
|
||||
//GPT backup header
|
||||
uint8_t *hdr_bak;
|
||||
std::vector<uint8_t> hdr_bak;
|
||||
//backup header crc
|
||||
uint32_t hdr_bak_crc;
|
||||
uint32_t hdr_bak_crc = 0;
|
||||
//Partition entries array
|
||||
uint8_t *pentry_arr;
|
||||
std::vector<uint8_t> pentry_arr;
|
||||
//Partition entries array for backup table
|
||||
uint8_t *pentry_arr_bak;
|
||||
std::vector<uint8_t> pentry_arr_bak;
|
||||
//Size of the pentry array
|
||||
uint32_t pentry_arr_size;
|
||||
uint32_t pentry_arr_size = 0;
|
||||
//Size of each element in the pentry array
|
||||
uint32_t pentry_size;
|
||||
uint32_t pentry_size = 0;
|
||||
//CRC of the partition entry array
|
||||
uint32_t pentry_arr_crc;
|
||||
uint32_t pentry_arr_crc = 0;
|
||||
//CRC of the backup partition entry array
|
||||
uint32_t pentry_arr_bak_crc;
|
||||
uint32_t pentry_arr_bak_crc = 0;
|
||||
//Path to block dev representing the disk
|
||||
char devpath[PATH_MAX];
|
||||
char devpath[PATH_MAX] = { 0 };
|
||||
//Block size of disk
|
||||
uint32_t block_size;
|
||||
uint32_t is_initialized;
|
||||
uint32_t block_size = 0;
|
||||
uint32_t is_initialized = 0;
|
||||
};
|
||||
|
||||
//GPT disk methods
|
||||
struct gpt_disk *gpt_disk_alloc();
|
||||
//Free previously allocated gpt_disk struct
|
||||
void gpt_disk_free(struct gpt_disk *disk);
|
||||
//Get the details of the disk holding the partition whose name
|
||||
//is passed in via dev
|
||||
int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk);
|
||||
|
22
qbootctl.cpp
22
qbootctl.cpp
@ -41,17 +41,23 @@ bool isslotnum(const char* str)
|
||||
return strspn(str, "01") == strlen(str);
|
||||
}
|
||||
|
||||
static void unexpectedSlot(const char *arg)
|
||||
{
|
||||
fprintf(stderr, "Expected slot not '%s'\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
unsigned parseSlot(const char* arg)
|
||||
{
|
||||
char *end;
|
||||
int slot;
|
||||
if (!isslot(arg)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!isslot(arg))
|
||||
unexpectedSlot(arg);
|
||||
|
||||
if (isslotnum(arg)) {
|
||||
slot = (int)strtol(arg, &end, 10);
|
||||
if (end == arg)
|
||||
goto fail;
|
||||
unexpectedSlot(arg);
|
||||
} else {
|
||||
switch (arg[0]) {
|
||||
case 'a':
|
||||
@ -63,17 +69,11 @@ unsigned parseSlot(const char* arg)
|
||||
slot = 1;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
unexpectedSlot(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return (unsigned)slot;
|
||||
|
||||
fail:
|
||||
fprintf(stderr,
|
||||
"Expected slot not '%s'\n",
|
||||
arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int usage()
|
||||
|
47
ufs-bsg.cpp
47
ufs-bsg.cpp
@ -48,34 +48,43 @@
|
||||
/* UFS BSG device node */
|
||||
static char ufs_bsg_dev[FNAME_SZ] = "/dev/bsg/ufs-bsg0";
|
||||
|
||||
static int fd_ufs_bsg = 0;
|
||||
struct fd_ufs_bsg {
|
||||
int fd = 0;
|
||||
|
||||
~fd_ufs_bsg()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (fd > 0) {
|
||||
::close(fd);
|
||||
fd = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static fd_ufs_bsg fd_ufs_bsg;
|
||||
|
||||
int ufs_bsg_dev_open()
|
||||
{
|
||||
if (fd_ufs_bsg)
|
||||
if (fd_ufs_bsg.fd)
|
||||
return 0;
|
||||
|
||||
fd_ufs_bsg = open(ufs_bsg_dev, O_RDWR);
|
||||
if (fd_ufs_bsg < 0) {
|
||||
fd_ufs_bsg.fd = open(ufs_bsg_dev, O_RDWR);
|
||||
if (fd_ufs_bsg.fd < 0) {
|
||||
fprintf(stderr, "Unable to open '%s': %s\n", ufs_bsg_dev,
|
||||
strerror(errno));
|
||||
fprintf(stderr,
|
||||
"Is CONFIG_SCSI_UFS_BSG is enabled in your kernel?\n");
|
||||
fd_ufs_bsg = 0;
|
||||
fd_ufs_bsg.fd = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ufs_bsg_dev_close()
|
||||
{
|
||||
if (fd_ufs_bsg) {
|
||||
close(fd_ufs_bsg);
|
||||
fd_ufs_bsg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int ufs_bsg_ioctl(int fd, struct ufs_bsg_request *req,
|
||||
struct ufs_bsg_reply *rsp, __u8 *buf, __u32 buf_len,
|
||||
enum bsg_ioctl_dir dir)
|
||||
@ -171,18 +180,18 @@ int32_t set_boot_lun(__u8 lun_id)
|
||||
ret = ufs_bsg_dev_open();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
LOGD("Opened ufs bsg dev: %s\n", ufs_bsg_dev);
|
||||
|
||||
ret = ufs_query_attr(fd_ufs_bsg, boot_lun_id, QUERY_REQ_FUNC_STD_WRITE,
|
||||
QUERY_REQ_OP_WRITE_ATTR, QUERY_ATTR_IDN_BOOT_LU_EN,
|
||||
0, 0);
|
||||
ret = ufs_query_attr(fd_ufs_bsg.fd, boot_lun_id,
|
||||
QUERY_REQ_FUNC_STD_WRITE, QUERY_REQ_OP_WRITE_ATTR,
|
||||
QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0);
|
||||
if (ret) {
|
||||
fprintf(stderr,
|
||||
"Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)",
|
||||
QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno);
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
ufs_bsg_dev_close();
|
||||
|
||||
fd_ufs_bsg.close();
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user