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. 325
      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,
};
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)) {
return retval;
if (gpt_disk_get_disk_info(partname, &disk)) {
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) {
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,15 +401,14 @@ int mark_boot_successful(unsigned slot)
if (update_slot_attribute(slot_suffix_arr[slot],
ATTR_BOOT_SUCCESSFUL)) {
goto error;
}
return 0;
error:
fprintf(stderr, "SLOT %s: Failed to mark boot successful\n",
slot_suffix_arr[slot]);
return -1;
}
return 0;
}
const char *get_suffix(unsigned slot)
{
if (boot_control_check_slot_sanity(slot) != 0)
@ -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)) {
if (gpt_disk_commit(&disk)) {
fprintf(stderr, "Failed to commit disk entry");
goto error;
}
gpt_disk_free(disk);
return -1;
}
return 0;
error:
if (disk)
gpt_disk_free(disk);
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;
}

@ -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;
}
return 0;
error:
if (set_boot_lun(boot_lun_id))
return -1;
return 0;
}
//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) {
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 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;
return 0;
}
//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

@ -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);

@ -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()

@ -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…
Cancel
Save