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.
merge-requests/8/head
Eric Curtin 2 years ago committed by Caleb Connolly
parent 843aa92266
commit 9d7600df51
  1. 238
      bootctrl_impl.cpp
  2. 329
      gpt-utils.cpp
  3. 30
      gpt-utils.h
  4. 22
      qbootctl.cpp
  5. 47
      ufs-bsg.cpp

@ -68,26 +68,42 @@ enum part_attr_type {
ATTR_BOOTABLE, 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) void get_kernel_cmdline_arg(const char *arg, char *buf, const char *def)
{ {
int fd; file file;
char pcmd[MAX_CMDLINE_SIZE]; char pcmd[MAX_CMDLINE_SIZE];
char *val, *found, *ptr = buf; char *val, *found, *ptr = buf;
fd = open("/proc/cmdline", O_RDONLY); file.open("/proc/cmdline");
int rc = read(fd, pcmd, MAX_CMDLINE_SIZE); int rc = read(file.fd, pcmd, MAX_CMDLINE_SIZE);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "Couldn't open /proc/cmdline: %d (%s)\n", rc, fprintf(stderr, "Couldn't open /proc/cmdline: %d (%s)\n", rc,
strerror(errno)); strerror(errno));
goto error; goto error;
} }
close(fd);
found = strstr(pcmd, arg); found = strstr(pcmd, arg);
if (!found || !(val = strstr(found, "="))) { if (!found || !(val = strstr(found, "="))) {
fprintf(stderr, "Couldn't find cmdline arg: '%s'\n", arg); fprintf(stderr, "Couldn't find cmdline arg: '%s'\n", arg);
goto error; goto error;
} }
val++; ++val;
// no this doesn't handle quotes lol // no this doesn't handle quotes lol
while (*val != ' ') { while (*val != ' ') {
*ptr++ = *val++; *ptr++ = *val++;
@ -103,28 +119,25 @@ error:
static int get_partition_attribute(char *partname, static int get_partition_attribute(char *partname,
enum part_attr_type part_attr) enum part_attr_type part_attr)
{ {
struct gpt_disk *disk = NULL; struct gpt_disk disk;
uint8_t *pentry = NULL; uint8_t *pentry = NULL;
int retval = -1; int retval = -1;
uint8_t *attr = NULL; uint8_t *attr = NULL;
if (!partname) if (!partname)
goto error; return retval;
disk = gpt_disk_alloc();
if (!disk) { if (gpt_disk_get_disk_info(partname, &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__); fprintf(stderr, "%s: Failed to get disk info\n", __func__);
goto error; return retval;
} }
pentry = gpt_disk_get_pentry(disk, partname, PRIMARY_GPT);
pentry = gpt_disk_get_pentry(&disk, partname, PRIMARY_GPT);
if (!pentry) { if (!pentry) {
fprintf(stderr, "%s: pentry does not exist in disk struct\n", fprintf(stderr, "%s: pentry does not exist in disk struct\n",
__func__); __func__);
goto error; return retval;
} }
attr = pentry + AB_FLAG_OFFSET; attr = pentry + AB_FLAG_OFFSET;
LOGD("get_partition_attribute() partname = %s, attr = 0x%x\n", partname, LOGD("get_partition_attribute() partname = %s, attr = 0x%x\n", partname,
*attr); *attr);
@ -138,14 +151,8 @@ static int get_partition_attribute(char *partname,
} else if (part_attr == ATTR_UNBOOTABLE) { } else if (part_attr == ATTR_UNBOOTABLE) {
retval = !!(*attr & AB_PARTITION_ATTR_UNBOOTABLE); retval = !!(*attr & AB_PARTITION_ATTR_UNBOOTABLE);
LOGD("AB_PARTITION_ATTR_UNBOOTABLE, retval = %d\n", retval); 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; return retval;
} }
@ -156,7 +163,7 @@ static int update_slot_attribute(const char *slot, enum part_attr_type ab_attr)
unsigned int i = 0; unsigned int i = 0;
char buf[PATH_MAX]; char buf[PATH_MAX];
struct stat st; struct stat st;
struct gpt_disk *disk = NULL; struct gpt_disk disk;
uint8_t *pentry = NULL; uint8_t *pentry = NULL;
uint8_t *pentry_bak = NULL; uint8_t *pentry_bak = NULL;
int rc = -1; 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; int slot_name_valid = 0;
if (!slot) { if (!slot) {
fprintf(stderr, "%s: Invalid argument\n", __func__); fprintf(stderr, "%s: Invalid argument\n", __func__);
goto error; return -1;
} }
for (i = 0; slot_suffix_arr[i] != NULL; i++) { for (i = 0; slot_suffix_arr[i] != NULL; i++) {
if (!strncmp(slot, slot_suffix_arr[i], if (!strncmp(slot, slot_suffix_arr[i],
strlen(slot_suffix_arr[i]))) strlen(slot_suffix_arr[i])))
slot_name_valid = 1; slot_name_valid = 1;
} }
if (!slot_name_valid) { if (!slot_name_valid) {
fprintf(stderr, "%s: Invalid slot name\n", __func__); fprintf(stderr, "%s: Invalid slot name\n", __func__);
goto error; return -1;
} }
for (i = 0; i < ARRAY_SIZE(ptn_list); i++) { for (i = 0; i < ARRAY_SIZE(ptn_list); i++) {
memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(buf));
//Check if A/B versions of this ptn exist //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)); memset(partName, '\0', sizeof(partName));
snprintf(partName, sizeof(partName) - 1, "%s%s", ptn_list[i], snprintf(partName, sizeof(partName) - 1, "%s%s", ptn_list[i],
slot); slot);
disk = gpt_disk_alloc(); rc = gpt_disk_get_disk_info(partName, &disk);
if (!disk) {
fprintf(stderr, "%s: Failed to alloc disk struct\n",
__func__);
goto error;
}
rc = gpt_disk_get_disk_info(partName, disk);
if (rc != 0) { if (rc != 0) {
fprintf(stderr, "%s: Failed to get disk info for %s\n", fprintf(stderr, "%s: Failed to get disk info for %s\n",
__func__, partName); __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) { if (!pentry || !pentry_bak) {
fprintf(stderr, fprintf(stderr,
"%s: Failed to get pentry/pentry_bak for %s\n", "%s: Failed to get pentry/pentry_bak for %s\n",
__func__, partName); __func__, partName);
goto error; return -1;
} }
attr = pentry + AB_FLAG_OFFSET; attr = pentry + AB_FLAG_OFFSET;
LOGD("%s: got pentry for part '%s': 0x%lx (at flags: 0x%x)\n", LOGD("%s: got pentry for part '%s': 0x%lx (at flags: 0x%x)\n",
__func__, partName, *(uint64_t *)pentry, *attr); __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; break;
default: default:
fprintf(stderr, "%s: Unrecognized attr\n", __func__); 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", fprintf(stderr, "%s: Failed to update crc for %s\n",
__func__, partName); __func__, partName);
goto error; return -1;
} }
if (gpt_disk_commit(disk)) {
if (gpt_disk_commit(&disk)) {
fprintf(stderr, fprintf(stderr,
"%s: Failed to write back entry for %s\n", "%s: Failed to write back entry for %s\n",
__func__, partName); __func__, partName);
goto error; return -1;
} }
gpt_disk_free(disk);
disk = NULL;
} }
return 0; 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() unsigned get_number_slots()
{ {
struct dirent *de = NULL; struct dirent *de = NULL;
DIR *dir_bootdev = NULL; dir dir_bootdev;
unsigned slot_count = 0; unsigned slot_count = 0;
dir_bootdev = opendir(BOOTDEV_DIR); if (!dir_bootdev.open(BOOTDEV_DIR)) {
if (!dir_bootdev) {
fprintf(stderr, "%s: Failed to open bootdev dir (%s)\n", fprintf(stderr, "%s: Failed to open bootdev dir (%s)\n",
__func__, strerror(errno)); __func__, strerror(errno));
goto error; return 0;
} }
while ((de = readdir(dir_bootdev))) {
while ((de = readdir(dir_bootdev.dir))) {
if (de->d_name[0] == '.') if (de->d_name[0] == '.')
continue; continue;
static_assert(AB_SLOT_A_SUFFIX[0] == '_', static_assert(AB_SLOT_A_SUFFIX[0] == '_',
@ -290,12 +310,8 @@ unsigned get_number_slots()
slot_count++; slot_count++;
} }
} }
closedir(dir_bootdev);
return slot_count; return slot_count;
error:
if (dir_bootdev)
closedir(dir_bootdev);
return 0;
} }
static unsigned int get_current_slot() static unsigned int get_current_slot()
@ -308,12 +324,14 @@ static unsigned int get_current_slot()
//Slot 0 is the only slot around. //Slot 0 is the only slot around.
return 0; return 0;
} }
get_kernel_cmdline_arg(BOOT_SLOT_PROP, bootSlotProp, "_a"); get_kernel_cmdline_arg(BOOT_SLOT_PROP, bootSlotProp, "_a");
if (!strncmp(bootSlotProp, "N/A\n", strlen("N/A"))) { if (!strncmp(bootSlotProp, "N/A\n", strlen("N/A"))) {
fprintf(stderr, "%s: Unable to read boot slot property\n", fprintf(stderr, "%s: Unable to read boot slot property\n",
__func__); __func__);
goto error; return 0;
} }
//Iterate through a list of partitons named as boot+suffix //Iterate through a list of partitons named as boot+suffix
//and see which one is currently active. //and see which one is currently active.
for (i = 0; slot_suffix_arr[i] != NULL; i++) { for (i = 0; slot_suffix_arr[i] != NULL; i++) {
@ -323,7 +341,7 @@ static unsigned int get_current_slot()
return i; return i;
} }
} }
error:
//The HAL spec requires that we return a number between //The HAL spec requires that we return a number between
//0 to num_slots - 1. Since something went wrong here we //0 to num_slots - 1. Since something went wrong here we
//are just going to return the default slot. //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], if (update_slot_attribute(slot_suffix_arr[slot],
ATTR_BOOT_SUCCESSFUL)) { ATTR_BOOT_SUCCESSFUL)) {
goto error;
}
return 0;
error:
fprintf(stderr, "SLOT %s: Failed to mark boot successful\n", fprintf(stderr, "SLOT %s: Failed to mark boot successful\n",
slot_suffix_arr[slot]); slot_suffix_arr[slot]);
return -1; return -1;
}
return 0;
} }
const char *get_suffix(unsigned slot) 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 //Return a gpt disk structure representing the disk that holds
//partition. //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) if (!partition)
return NULL; return false;
disk = gpt_disk_alloc();
if (!disk) {
fprintf(stderr, "%s: Failed to alloc disk\n", __func__);
goto error;
}
if (gpt_disk_get_disk_info(partition, disk)) { if (gpt_disk_get_disk_info(partition, disk)) {
fprintf(stderr, "failed to get disk info for %s\n", partition); fprintf(stderr, "failed to get disk info for %s\n", partition);
goto error; return false;
} }
return disk;
error: return true;
if (disk)
gpt_disk_free(disk);
return NULL;
} }
//The argument here is a vector of partition names(including the slot suffix) //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) unsigned slot)
{ {
char buf[PATH_MAX] = { 0 }; char buf[PATH_MAX] = { 0 };
struct gpt_disk *disk = NULL; struct gpt_disk disk;
char slotA[MAX_GPT_NAME_SIZE + 1] = { 0 }; char slotA[MAX_GPT_NAME_SIZE + 1] = { 0 };
char slotB[MAX_GPT_NAME_SIZE + 1] = { 0 }; char slotB[MAX_GPT_NAME_SIZE + 1] = { 0 };
char active_guid[TYPE_GUID_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)) { if (prefix.size() < (strlen(AB_SLOT_A_SUFFIX) + 1)) {
fprintf(stderr, "Invalid partition name: %s\n", fprintf(stderr, "Invalid partition name: %s\n",
prefix.c_str()); prefix.c_str());
goto error; return -1;
} }
prefix.resize(prefix.size() - strlen(AB_SLOT_A_SUFFIX)); prefix.resize(prefix.size() - strlen(AB_SLOT_A_SUFFIX));
//Check if A/B versions of this ptn exist //Check if A/B versions of this ptn exist
snprintf(buf, sizeof(buf) - 1, "%s/%s%s", BOOT_DEV_DIR, 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); AB_SLOT_A_SUFFIX);
snprintf(slotB, sizeof(slotB) - 1, "%s%s", prefix.c_str(), snprintf(slotB, sizeof(slotB) - 1, "%s%s", prefix.c_str(),
AB_SLOT_B_SUFFIX); AB_SLOT_B_SUFFIX);
//Get the disk containing the partitions that were passed in. //Get the disk containing the partitions that were passed in.
//All partitions passed in must lie on the same disk. //All partitions passed in must lie on the same disk.
if (!disk) { if (!boot_ctl_get_disk_info(slotA, &disk))
disk = boot_ctl_get_disk_info(slotA); return -1;
if (!disk)
goto error;
}
//Get partition entry for slot A & B from the primary //Get partition entry for slot A & B from the primary
//and backup tables. //and backup tables.
pentryA = gpt_disk_get_pentry(disk, slotA, PRIMARY_GPT); pentryA = gpt_disk_get_pentry(&disk, slotA, PRIMARY_GPT);
pentryA_bak = gpt_disk_get_pentry(disk, slotA, SECONDARY_GPT); pentryA_bak = gpt_disk_get_pentry(&disk, slotA, SECONDARY_GPT);
pentryB = gpt_disk_get_pentry(disk, slotB, PRIMARY_GPT); pentryB = gpt_disk_get_pentry(&disk, slotB, PRIMARY_GPT);
pentryB_bak = gpt_disk_get_pentry(disk, slotB, SECONDARY_GPT); pentryB_bak = gpt_disk_get_pentry(&disk, slotB, SECONDARY_GPT);
if (!pentryA || !pentryA_bak || !pentryB || !pentryB_bak) { if (!pentryA || !pentryA_bak || !pentryB || !pentryB_bak) {
//None of these should be NULL since we have already //None of these should be NULL since we have already
//checked for A & B versions earlier. //checked for A & B versions earlier.
fprintf(stderr, "Slot pentries for %s not found.\n", fprintf(stderr, "Slot pentries for %s not found.\n",
prefix.c_str()); prefix.c_str());
goto error; return -1;
} }
LOGD("\tAB attr (A): 0x%x (backup: 0x%x)\n", LOGD("\tAB attr (A): 0x%x (backup: 0x%x)\n",
*(uint16_t *)(pentryA + AB_FLAG_OFFSET), *(uint16_t *)(pentryA + AB_FLAG_OFFSET),
*(uint16_t *)(pentryA_bak + 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); TYPE_GUID_SIZE);
} else { } else {
fprintf(stderr, "Both A & B are inactive..Aborting"); fprintf(stderr, "Both A & B are inactive..Aborting");
goto error; return -1;
} }
// printf("\tActive GUID: %s\n", active_guid); // printf("\tActive GUID: %s\n", active_guid);
// printf("\tInactive GUID: %s\n", active_guid); // printf("\tInactive GUID: %s\n", active_guid);
if (!strncmp(slot_suffix_arr[slot], AB_SLOT_A_SUFFIX, 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 { } else {
//Something has gone terribly terribly wrong //Something has gone terribly terribly wrong
fprintf(stderr, "%s: Unknown slot suffix!\n", __func__); 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", fprintf(stderr, "%s: Failed to update gpt_disk crc\n",
__func__); __func__);
goto error; return -1;
} }
} }
//write updated content to disk //write updated content to disk
if (disk) { if (gpt_disk_commit(&disk)) {
if (gpt_disk_commit(disk)) {
fprintf(stderr, "Failed to commit disk entry"); fprintf(stderr, "Failed to commit disk entry");
goto error; return -1;
}
gpt_disk_free(disk);
} }
return 0;
error: return 0;
if (disk)
gpt_disk_free(disk);
return -1;
} }
unsigned get_active_boot_slot() unsigned get_active_boot_slot()
@ -607,13 +613,13 @@ int set_active_boot_slot(unsigned slot)
if (boot_control_check_slot_sanity(slot)) { if (boot_control_check_slot_sanity(slot)) {
fprintf(stderr, "%s: Bad arguments\n", __func__); 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); ismmc = gpt_utils_is_partition_backed_by_emmc(PTN_XBL AB_SLOT_A_SUFFIX);
if (!ismmc && ufs_bsg_dev_open() < 0) { if (!ismmc && ufs_bsg_dev_open() < 0) {
goto error; return -1;
} }
//The partition list just contains prefixes(without the _a/_b) of the //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); cur_ptn.append(AB_SLOT_A_SUFFIX);
ptn_vec.push_back(cur_ptn); ptn_vec.push_back(cur_ptn);
} }
//The partition map gives us info in the following format: //The partition map gives us info in the following format:
// [path_to_block_device_1]--><partitions on device 1> // [path_to_block_device_1]--><partitions on device 1>
// [path_to_block_device_2]--><partitions on device 2> // [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,....> // [/dev/block/sdb]---><system, boot, rpm, tz,....>
if (gpt_utils_get_partition_map(ptn_vec, ptn_map)) { if (gpt_utils_get_partition_map(ptn_vec, ptn_map)) {
fprintf(stderr, "%s: Failed to get partition map\n", __func__); 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(); for (map_iter = ptn_map.begin(); map_iter != ptn_map.end();
map_iter++) { map_iter++) {
if (map_iter->second.size() < 1) if (map_iter->second.size() < 1)
@ -649,8 +657,7 @@ int set_active_boot_slot(unsigned slot)
fprintf(stderr, fprintf(stderr,
"%s: Failed to set active slot for partitions \n", "%s: Failed to set active slot for partitions \n",
__func__); __func__);
; return -1;
goto error;
} }
} }
@ -669,19 +676,17 @@ int set_active_boot_slot(unsigned slot)
} else { } else {
//Something has gone terribly terribly wrong //Something has gone terribly terribly wrong
fprintf(stderr, "%s: Unknown slot suffix!\n", __func__); fprintf(stderr, "%s: Unknown slot suffix!\n", __func__);
goto error; return -1;
} }
if (rc) { if (rc) {
fprintf(stderr, fprintf(stderr,
"%s: Failed to switch xbl boot partition\n", "%s: Failed to switch xbl boot partition\n",
__func__); __func__);
goto error; return -1;
} }
return 0; return 0;
error:
return -1;
} }
int set_slot_as_unbootable(unsigned slot) 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) { if (boot_control_check_slot_sanity(slot) != 0) {
fprintf(stderr, "%s: Argument check failed\n", __func__); fprintf(stderr, "%s: Argument check failed\n", __func__);
goto error; return -1;
} }
snprintf(bootPartition, sizeof(bootPartition) - 1, "boot%s", snprintf(bootPartition, sizeof(bootPartition) - 1, "boot%s",
slot_suffix_arr[slot]); slot_suffix_arr[slot]);
attr = get_partition_attribute(bootPartition, ATTR_BOOT_SUCCESSFUL); attr = get_partition_attribute(bootPartition, ATTR_BOOT_SUCCESSFUL);
LOGD("%s: slot = %d, attr = 0x%x\n", __func__, slot, attr); LOGD("%s: slot = %d, attr = 0x%x\n", __func__, slot, attr);
if (attr >= 0) if (attr >= 0)
return attr; return attr;
error:
return -1; return -1;
} }

@ -272,7 +272,7 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
else { else {
fprintf(stderr, "%s: Failed to locate secondary xbl\n", fprintf(stderr, "%s: Failed to locate secondary xbl\n",
__func__); __func__);
goto error; return -1;
} }
} else if (chain == NORMAL_BOOT) { } else if (chain == NORMAL_BOOT) {
boot_lun_id = BOOT_LUN_A_ID; boot_lun_id = BOOT_LUN_A_ID;
@ -283,28 +283,28 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
else { else {
fprintf(stderr, "%s: Failed to locate primary xbl\n", fprintf(stderr, "%s: Failed to locate primary xbl\n",
__func__); __func__);
goto error; return -1;
} }
} else { } else {
fprintf(stderr, "%s: Invalid boot chain id\n", __func__); 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 //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. //the same time. If not the current configuration is invalid.
if ((stat(XBL_PRIMARY, &st) || stat(XBL_BACKUP, &st)) && if ((stat(XBL_PRIMARY, &st) || stat(XBL_BACKUP, &st)) &&
(stat(XBL_AB_PRIMARY, &st) || stat(XBL_AB_SECONDARY, &st))) { (stat(XBL_AB_PRIMARY, &st) || stat(XBL_AB_SECONDARY, &st))) {
fprintf(stderr, "%s:primary/secondary XBL prt not found(%s)\n", fprintf(stderr, "%s:primary/secondary XBL prt not found(%s)\n",
__func__, strerror(errno)); __func__, strerror(errno));
goto error; return -1;
} }
LOGD("%s: setting %s lun as boot lun\n", __func__, boot_dev); LOGD("%s: setting %s lun as boot lun\n", __func__, boot_dev);
if (set_boot_lun(boot_lun_id)) { if (set_boot_lun(boot_lun_id))
goto error;
}
return 0;
error:
return -1; return -1;
return 0;
} }
//Given a parttion name(eg: rpm) get the path to the block device that //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; uint32_t block_size = 0;
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "%s: invalid descriptor\n", __func__); fprintf(stderr, "%s: invalid descriptor\n", __func__);
goto error; return 0;
} }
if (ioctl(fd, BLKSSZGET, &block_size) != 0) { if (ioctl(fd, BLKSSZGET, &block_size) != 0) {
fprintf(stderr, "%s: Failed to get GPT dev block size : %s\n", fprintf(stderr, "%s: Failed to get GPT dev block size : %s\n",
__func__, strerror(errno)); __func__, strerror(errno));
goto error; return 0;
} }
return block_size; return block_size;
error:
return 0;
} }
//Write the GPT header present in the passed in buffer back to the //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; off_t gpt_header_offset = 0;
if (!gpt_header || fd < 0) { if (!gpt_header || fd < 0) {
fprintf(stderr, "%s: Invalid arguments\n", __func__); fprintf(stderr, "%s: Invalid arguments\n", __func__);
goto error; return -1;
} }
block_size = gpt_get_block_size(fd); block_size = gpt_get_block_size(fd);
LOGD("%s: Block size is : %d\n", __func__, block_size); LOGD("%s: Block size is : %d\n", __func__, block_size);
if (block_size == 0) { if (block_size == 0) {
fprintf(stderr, "%s: Failed to get block size\n", __func__); fprintf(stderr, "%s: Failed to get block size\n", __func__);
goto error; return -1;
} }
if (instance == PRIMARY_GPT) if (instance == PRIMARY_GPT)
gpt_header_offset = block_size; gpt_header_offset = block_size;
else else
gpt_header_offset = lseek64(fd, 0, SEEK_END) - block_size; gpt_header_offset = lseek64(fd, 0, SEEK_END) - block_size;
if (gpt_header_offset <= 0) { if (gpt_header_offset <= 0) {
fprintf(stderr, "%s: Failed to get gpt header offset\n", fprintf(stderr, "%s: Failed to get gpt header offset\n",
__func__); __func__);
goto error; return -1;
} }
LOGD("%s: Writing back header to offset %ld\n", __func__, LOGD("%s: Writing back header to offset %ld\n", __func__,
gpt_header_offset); gpt_header_offset);
if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) { if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) {
fprintf(stderr, "%s: Failed to write back GPT header\n", fprintf(stderr, "%s: Failed to write back GPT header\n",
__func__); __func__);
goto error; return -1;
} }
return 0; 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 //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 }; char devpath[PATH_MAX] = { 0 };
off_t hdr_offset = 0; off_t hdr_offset = 0;
uint32_t block_size = 0; uint32_t block_size = 0;
int fd = -1; file file;
if (!partname) { if (!partname) {
fprintf(stderr, "%s: Invalid partition name\n", __func__); fprintf(stderr, "%s: Invalid partition name\n", __func__);
goto error; return false;
} }
if (get_dev_path_from_partition_name(partname, devpath, if (get_dev_path_from_partition_name(partname, devpath,
sizeof(devpath)) != 0) { sizeof(devpath)) != 0) {
fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__, fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__,
partname); partname);
goto error; return false;
} }
fd = open(devpath, O_RDWR);
if (fd < 0) { if (file.open(devpath) < 0) {
fprintf(stderr, "%s: Failed to open %s : %s\n", __func__, fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
devpath, strerror(errno)); 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) { if (block_size == 0) {
fprintf(stderr, "%s: Failed to get gpt block size for %s\n", fprintf(stderr, "%s: Failed to get gpt block size for %s\n",
__func__, partname); __func__, partname);
goto error; return false;
} }
hdr = (uint8_t *)calloc(block_size, 1); hdr->resize(block_size);
if (!hdr) { std::fill(hdr->begin(), hdr->end(), 0);
fprintf(stderr,
"%s: Failed to allocate memory for gpt header\n",
__func__);
}
if (instance == PRIMARY_GPT) if (instance == PRIMARY_GPT)
hdr_offset = block_size; hdr_offset = block_size;
else { else
hdr_offset = lseek64(fd, 0, SEEK_END) - block_size; hdr_offset = lseek64(file.fd, 0, SEEK_END) - block_size;
}
if (hdr_offset < 0) { if (hdr_offset < 0) {
fprintf(stderr, "%s: Failed to get gpt header offset\n", fprintf(stderr, "%s: Failed to get gpt header offset\n",
__func__); __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", fprintf(stderr, "%s: Failed to read GPT header from device\n",
__func__); __func__);
goto error; return false;
} }
//DumpHex(hdr, block_size);
close(fd); return true;
return hdr;
error:
if (fd >= 0)
close(fd);
if (hdr)
free(hdr);
return NULL;
} }
//Returns the partition entry array based on the //Returns the partition entry array based on the
//passed in buffer which contains the gpt header. //passed in buffer which contains the gpt header.
//The fd here is the descriptor for the 'disk' which //The fd here is the descriptor for the 'disk' which
//holds the partition //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; uint64_t pentries_start = 0;
uint32_t pentry_size = 0; uint32_t pentry_size = 0;
uint32_t block_size = 0; uint32_t block_size = 0;
uint32_t pentries_arr_size = 0; uint32_t pentries_arr_size = 0;
uint8_t *pentry_arr = NULL;
int rc = 0; int rc = 0;
if (!hdr) {
fprintf(stderr, "%s: Invalid header\n", __func__);
goto error;
}
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "%s: Invalid fd\n", __func__); fprintf(stderr, "%s: Invalid fd\n", __func__);
goto error; return false;
} }
block_size = gpt_get_block_size(fd); block_size = gpt_get_block_size(fd);
if (!block_size) { if (!block_size) {
fprintf(stderr, "%s: Failed to get gpt block size for\n", fprintf(stderr, "%s: Failed to get gpt block size for\n",
__func__); __func__);
goto error; return false;
} }
pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size; pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET); pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
pentries_arr_size = pentries_arr_size =
GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size; GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
pentry_arr = (uint8_t *)calloc(1, pentries_arr_size); pentry_arr->resize(pentries_arr_size);
if (!pentry_arr) { std::fill(pentry_arr->begin(), pentry_arr->end(), 0);
fprintf(stderr, rc = blk_rw(fd, 0, pentries_start, pentry_arr->data(),
"%s: Failed to allocate memory for partition array\n", pentries_arr_size);
__func__);
goto error;
}
rc = blk_rw(fd, 0, pentries_start, pentry_arr, pentries_arr_size);
if (rc) { if (rc) {
fprintf(stderr, "%s: Failed to read partition entry array\n", fprintf(stderr, "%s: Failed to read partition entry array\n",
__func__); __func__);
goto error; return false;
} }
return pentry_arr;
error: return true;
if (pentry_arr)
free(pentry_arr);
return NULL;
} }
static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t *arr) 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; int rc = 0;
if (!hdr || fd < 0 || !arr) { if (!hdr || fd < 0 || !arr) {
fprintf(stderr, "%s: Invalid argument\n", __func__); fprintf(stderr, "%s: Invalid argument\n", __func__);
goto error; return -1;
} }
block_size = gpt_get_block_size(fd); block_size = gpt_get_block_size(fd);
if (!block_size) { if (!block_size) {
fprintf(stderr, "%s: Failed to get gpt block size for\n", fprintf(stderr, "%s: Failed to get gpt block size for\n",
__func__); __func__);
goto error; return -1;
} }
LOGD("%s : Block size is %d\n", __func__, block_size); LOGD("%s : Block size is %d\n", __func__, block_size);
pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size; pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET); 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) { if (rc) {
fprintf(stderr, "%s: Failed to read partition entry array\n", fprintf(stderr, "%s: Failed to read partition entry array\n",
__func__); __func__);
goto error;
}
return 0;
error:
return -1; 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 return 0;
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 //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. //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; file file;
int fd = -1;
uint32_t gpt_header_size = 0; uint32_t gpt_header_size = 0;
if (!dsk || !dev) { if (!disk || !dev) {
fprintf(stderr, "%s: Invalid arguments\n", __func__); fprintf(stderr, "%s: Invalid arguments\n", __func__);
goto error; return -1;
} }
disk = dsk;
disk->hdr = gpt_get_header(dev, PRIMARY_GPT); gpt_get_header(dev, PRIMARY_GPT, &disk->hdr);
if (!disk->hdr) { if (disk->hdr.empty()) {
fprintf(stderr, "%s: Failed to get primary header\n", __func__); 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 // FIXME: pointer offsets crc bleh
disk->hdr_crc = crc32(0, disk->hdr, gpt_header_size); disk->hdr_crc = crc32(0, disk->hdr.data(), gpt_header_size);
disk->hdr_bak = gpt_get_header(dev, PRIMARY_GPT); gpt_get_header(dev, PRIMARY_GPT, &disk->hdr_bak);
if (!disk->hdr_bak) { if (disk->hdr_bak.empty()) {
fprintf(stderr, "%s: Failed to get backup header\n", __func__); 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 //Descriptor for the block device. We will use this for further
//modifications to the partition table //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) { sizeof(disk->devpath)) != 0) {
fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__, fprintf(stderr, "%s: Failed to resolve path for %s\n", __func__,
dev); 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__, fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
disk->devpath, strerror(errno)); 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", fprintf(stderr, "%s: Failed to obtain partition entry array\n",
__func__); __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, fprintf(stderr,
"%s: Failed to obtain backup partition entry array\n", "%s: Failed to obtain backup partition entry array\n",
__func__); __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 = 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_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 = disk->pentry_arr_bak_crc =
GET_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET); GET_4_BYTES(disk->hdr_bak.data() + PARTITION_CRC_OFFSET);
disk->block_size = gpt_get_block_size(fd); disk->block_size = gpt_get_block_size(file.fd);
close(fd);
disk->is_initialized = GPT_DISK_INIT_MAGIC; disk->is_initialized = GPT_DISK_INIT_MAGIC;
return 0; return 0;
error:
if (fd >= 0)
close(fd);
return -1;
} }
//Get pointer to partition entry from a allocated gpt_disk structure //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; uint8_t *ptn_arr = NULL;
if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) { if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) {
fprintf(stderr, "%s: Invalid argument\n", __func__); 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, return (gpt_pentry_seek(partname, ptn_arr,
ptn_arr + disk->pentry_arr_size, ptn_arr + disk->pentry_arr_size,
disk->pentry_size)); disk->pentry_size));
error:
return NULL;
} }
//Update CRC values for the various components of the gpt_disk //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; uint32_t gpt_header_size = 0;
if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) { if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
fprintf(stderr, "%s: invalid argument\n", __func__); fprintf(stderr, "%s: invalid argument\n", __func__);
goto error; return -1;
} }
//Recalculate the CRC of the primary partiton array //Recalculate the CRC of the primary partiton array
disk->pentry_arr_crc = 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 //Recalculate the CRC of the backup partition array
disk->pentry_arr_bak_crc = 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 //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 //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); disk->pentry_arr_bak_crc);
//Update the CRC value of the primary header //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 //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.data() + HEADER_CRC_OFFSET, 0);
PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, 0); PUT_4_BYTES(disk->hdr_bak.data() + HEADER_CRC_OFFSET, 0);
disk->hdr_crc = crc32(0, disk->hdr, gpt_header_size); disk->hdr_crc = crc32(0, disk->hdr.data(), gpt_header_size);
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);
PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, disk->hdr_crc); PUT_4_BYTES(disk->hdr.data() + HEADER_CRC_OFFSET, disk->hdr_crc);
PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, disk->hdr_bak_crc); PUT_4_BYTES(disk->hdr_bak.data() + HEADER_CRC_OFFSET,
disk->hdr_bak_crc);
return 0; return 0;
error:
return -1;
} }
//Write the contents of struct gpt_disk back to the actual disk //Write the contents of struct gpt_disk back to the actual disk
int gpt_disk_commit(struct gpt_disk *disk) int gpt_disk_commit(struct gpt_disk *disk)
{ {
int fd = -1; file file;
if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) { if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
fprintf(stderr, "%s: Invalid args\n", __func__); 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__, fprintf(stderr, "%s: Failed to open %s: %s\n", __func__,
disk->devpath, strerror(errno)); disk->devpath, strerror(errno));
goto error; return -1;
} }
LOGD("%s: Writing back primary GPT header\n", __func__); LOGD("%s: Writing back primary GPT header\n", __func__);
//Write the primary header //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", fprintf(stderr, "%s: Failed to update primary GPT header\n",
__func__); __func__);
goto error; return -1;
} }
LOGD("%s: Writing back primary partition array\n", __func__); LOGD("%s: Writing back primary partition array\n", __func__);
//Write back the primary partition array //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, fprintf(stderr,
"%s: Failed to write primary GPT partition arr\n", "%s: Failed to write primary GPT partition arr\n",
__func__); __func__);
goto error; return -1;
} }
fsync(fd);
close(fd);
return 0; return 0;
error:
if (fd >= 0)
close(fd);
return -1;
} }
//Determine whether to handle the given partition as eMMC or UFS, using the //Determine whether to handle the given partition as eMMC or UFS, using the

@ -96,36 +96,32 @@ enum boot_chain { NORMAL_BOOT = 0, BACKUP_BOOT };
struct gpt_disk { struct gpt_disk {
//GPT primary header //GPT primary header
uint8_t *hdr; std::vector<uint8_t> hdr;
//primary header crc //primary header crc
uint32_t hdr_crc; uint32_t hdr_crc = 0;
//GPT backup header //GPT backup header
uint8_t *hdr_bak; std::vector<uint8_t> hdr_bak;
//backup header crc //backup header crc
uint32_t hdr_bak_crc; uint32_t hdr_bak_crc = 0;
//Partition entries array //Partition entries array
uint8_t *pentry_arr; std::vector<uint8_t> pentry_arr;
//Partition entries array for backup table //Partition entries array for backup table
uint8_t *pentry_arr_bak; std::vector<uint8_t> pentry_arr_bak;
//Size of the pentry array //Size of the pentry array
uint32_t pentry_arr_size; uint32_t pentry_arr_size = 0;
//Size of each element in the pentry array //Size of each element in the pentry array
uint32_t pentry_size; uint32_t pentry_size = 0;
//CRC of the partition entry array //CRC of the partition entry array
uint32_t pentry_arr_crc; uint32_t pentry_arr_crc = 0;
//CRC of the backup partition entry array //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 //Path to block dev representing the disk
char devpath[PATH_MAX]; char devpath[PATH_MAX] = { 0 };
//Block size of disk //Block size of disk
uint32_t block_size; uint32_t block_size = 0;
uint32_t is_initialized; 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 //Get the details of the disk holding the partition whose name
//is passed in via dev //is passed in via dev
int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk); int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk);

@ -41,17 +41,23 @@ bool isslotnum(const char* str)
return strspn(str, "01") == strlen(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) unsigned parseSlot(const char* arg)
{ {
char *end; char *end;
int slot; int slot;
if (!isslot(arg)) { if (!isslot(arg))
goto fail; unexpectedSlot(arg);
}
if (isslotnum(arg)) { if (isslotnum(arg)) {
slot = (int)strtol(arg, &end, 10); slot = (int)strtol(arg, &end, 10);
if (end == arg) if (end == arg)
goto fail; unexpectedSlot(arg);
} else { } else {
switch (arg[0]) { switch (arg[0]) {
case 'a': case 'a':
@ -63,17 +69,11 @@ unsigned parseSlot(const char* arg)
slot = 1; slot = 1;
break; break;
default: default:
goto fail; unexpectedSlot(arg);
} }
} }
return (unsigned)slot; return (unsigned)slot;
fail:
fprintf(stderr,
"Expected slot not '%s'\n",
arg);
exit(1);
} }
int usage() int usage()

@ -48,34 +48,43 @@
/* UFS BSG device node */ /* UFS BSG device node */
static char ufs_bsg_dev[FNAME_SZ] = "/dev/bsg/ufs-bsg0"; 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() int ufs_bsg_dev_open()
{ {
if (fd_ufs_bsg) if (fd_ufs_bsg.fd)
return 0; return 0;
fd_ufs_bsg = open(ufs_bsg_dev, O_RDWR); fd_ufs_bsg.fd = open(ufs_bsg_dev, O_RDWR);
if (fd_ufs_bsg < 0) { if (fd_ufs_bsg.fd < 0) {
fprintf(stderr, "Unable to open '%s': %s\n", ufs_bsg_dev, fprintf(stderr, "Unable to open '%s': %s\n", ufs_bsg_dev,
strerror(errno)); strerror(errno));
fprintf(stderr, fprintf(stderr,
"Is CONFIG_SCSI_UFS_BSG is enabled in your kernel?\n"); "Is CONFIG_SCSI_UFS_BSG is enabled in your kernel?\n");
fd_ufs_bsg = 0; fd_ufs_bsg.fd = 0;
return -1; return -1;
} }
return 0; 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, static int ufs_bsg_ioctl(int fd, struct ufs_bsg_request *req,
struct ufs_bsg_reply *rsp, __u8 *buf, __u32 buf_len, struct ufs_bsg_reply *rsp, __u8 *buf, __u32 buf_len,
enum bsg_ioctl_dir dir) enum bsg_ioctl_dir dir)
@ -171,18 +180,18 @@ int32_t set_boot_lun(__u8 lun_id)
ret = ufs_bsg_dev_open(); ret = ufs_bsg_dev_open();
if (ret) if (ret)
return ret; return ret;
LOGD("Opened ufs bsg dev: %s\n", ufs_bsg_dev); 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, ret = ufs_query_attr(fd_ufs_bsg.fd, boot_lun_id,
QUERY_REQ_OP_WRITE_ATTR, QUERY_ATTR_IDN_BOOT_LU_EN, QUERY_REQ_FUNC_STD_WRITE, QUERY_REQ_OP_WRITE_ATTR,
0, 0); QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0);
if (ret) { if (ret) {
fprintf(stderr, fprintf(stderr,
"Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)", "Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)",
QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno); QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno);
goto out;
} }
out:
ufs_bsg_dev_close(); fd_ufs_bsg.close();
return ret; return ret;
} }

Loading…
Cancel
Save