mirror of
https://github.com/linux-msm/qbootctl.git
synced 2026-02-25 13:13:44 -08:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39a6e6daaf | ||
|
|
e1d7c370bc | ||
|
|
413ee35eda | ||
|
|
d30d9dfc03 |
@@ -51,8 +51,9 @@ struct boot_control_module {
|
|||||||
* The returned value is always guaranteed to be strictly less than the
|
* The returned value is always guaranteed to be strictly less than the
|
||||||
* value returned by getNumberSlots. Slots start at 0 and
|
* value returned by getNumberSlots. Slots start at 0 and
|
||||||
* finish at getNumberSlots() - 1
|
* finish at getNumberSlots() - 1
|
||||||
|
* Returns -ENOENT on devices with no slots.
|
||||||
*/
|
*/
|
||||||
unsigned (*getCurrentSlot)();
|
int (*getCurrentSlot)();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (*markBootSuccessful)() marks the specified slot
|
* (*markBootSuccessful)() marks the specified slot
|
||||||
|
|||||||
@@ -331,21 +331,50 @@ int get_boot_attr(struct gpt_disk *disk, unsigned slot, enum part_attr_type attr
|
|||||||
return get_partition_attribute(disk, bootPartition, attr);
|
return get_partition_attribute(disk, bootPartition, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int get_current_slot_from_kernel_cmdline()
|
unsigned get_active_boot_slot()
|
||||||
{
|
{
|
||||||
uint32_t num_slots = 0;
|
struct gpt_disk disk = { 0 };
|
||||||
char bootSlotProp[MAX_CMDLINE_SIZE] = { '\0' };
|
uint32_t num_slots = get_number_slots();
|
||||||
unsigned i = 0;
|
|
||||||
num_slots = get_number_slots();
|
|
||||||
if (num_slots <= 1) {
|
if (num_slots <= 1) {
|
||||||
// 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");
|
for (uint32_t i = 0; i < num_slots; i++) {
|
||||||
|
if (get_boot_attr(&disk, i, ATTR_SLOT_ACTIVE)) {
|
||||||
|
gpt_disk_free(&disk);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: Failed to find the active boot slot\n", __func__);
|
||||||
|
gpt_disk_free(&disk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The current slot is usually made available via the kernel cmdline. If it isn't for some reason
|
||||||
|
* (e.g. because we booted via a secondary bootloader that removes Android cmdline args) then we
|
||||||
|
* assume that the active slot is the current slot
|
||||||
|
*/
|
||||||
|
static int get_current_or_active_slot()
|
||||||
|
{
|
||||||
|
uint32_t num_slots = 0;
|
||||||
|
char bootSlotProp[MAX_CMDLINE_SIZE] = { '\0' };
|
||||||
|
unsigned i = 0;
|
||||||
|
num_slots = get_number_slots();
|
||||||
|
if (num_slots == 0)
|
||||||
|
return -ENOENT;
|
||||||
|
if (num_slots == 1) {
|
||||||
|
// Slot 0 is the only slot around.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_kernel_cmdline_arg(BOOT_SLOT_PROP, bootSlotProp, "N/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", __func__);
|
fprintf(stderr, "%s: Unable to read boot slot property\n", __func__);
|
||||||
return 0;
|
return get_active_boot_slot();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through a list of partitons named as boot+suffix
|
// Iterate through a list of partitons named as boot+suffix
|
||||||
@@ -538,28 +567,6 @@ static int boot_ctl_set_active_slot_for_partitions(struct gpt_disk *disk,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned get_active_boot_slot()
|
|
||||||
{
|
|
||||||
struct gpt_disk disk = { 0 };
|
|
||||||
uint32_t num_slots = get_number_slots();
|
|
||||||
|
|
||||||
if (num_slots <= 1) {
|
|
||||||
// Slot 0 is the only slot around.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < num_slots; i++) {
|
|
||||||
if (get_boot_attr(&disk, i, ATTR_SLOT_ACTIVE)) {
|
|
||||||
gpt_disk_free(&disk);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: Failed to find the active boot slot\n", __func__);
|
|
||||||
gpt_disk_free(&disk);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int set_active_boot_slot(unsigned slot, bool ignore_missing_bsg)
|
int set_active_boot_slot(unsigned slot, bool ignore_missing_bsg)
|
||||||
{
|
{
|
||||||
enum boot_chain chain = (enum boot_chain)slot;
|
enum boot_chain chain = (enum boot_chain)slot;
|
||||||
@@ -638,7 +645,7 @@ int is_slot_marked_successful(unsigned slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct boot_control_module bootctl = {
|
const struct boot_control_module bootctl = {
|
||||||
.getCurrentSlot = get_current_slot_from_kernel_cmdline,
|
.getCurrentSlot = get_current_or_active_slot,
|
||||||
.markBootSuccessful = mark_boot_successful,
|
.markBootSuccessful = mark_boot_successful,
|
||||||
.setActiveBootSlot = set_active_boot_slot,
|
.setActiveBootSlot = set_active_boot_slot,
|
||||||
.setSlotAsUnbootable = set_slot_as_unbootable,
|
.setSlotAsUnbootable = set_slot_as_unbootable,
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ static int gpt_get_headers(const char *partname, uint8_t **primary, uint8_t **ba
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open(devpath, O_RDWR);
|
fd = open(devpath, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "%s: Failed to open %s : %s\n", __func__, devpath, strerror(errno));
|
fprintf(stderr, "%s: Failed to open %s : %s\n", __func__, devpath, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -613,6 +613,11 @@ int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (disk->is_initialized == GPT_DISK_INIT_MAGIC) {
|
if (disk->is_initialized == GPT_DISK_INIT_MAGIC) {
|
||||||
|
/* Commit any changes to the disk */
|
||||||
|
if (gpt_disk_commit(disk)) {
|
||||||
|
fprintf(stderr, "Failed to commit disk entry");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
// We already have a valid disk handle. Free it.
|
// We already have a valid disk handle. Free it.
|
||||||
LOGD("%s: Freeing disk handle for %s... -> %s\n", __func__, disk->devpath, devpath);
|
LOGD("%s: Freeing disk handle for %s... -> %s\n", __func__, disk->devpath, devpath);
|
||||||
gpt_disk_free(disk);
|
gpt_disk_free(disk);
|
||||||
@@ -638,7 +643,7 @@ int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *disk)
|
|||||||
|
|
||||||
disk->hdr_bak_crc = efi_crc32(disk->hdr_bak, gpt_header_size);
|
disk->hdr_bak_crc = efi_crc32(disk->hdr_bak, gpt_header_size);
|
||||||
|
|
||||||
fd = open(disk->devpath, O_RDWR);
|
fd = open(disk->devpath, O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "%s: Failed to open %s: %s\n", __func__, disk->devpath,
|
fprintf(stderr, "%s: Failed to open %s: %s\n", __func__, disk->devpath,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
|||||||
20
qbootctl.c
20
qbootctl.c
@@ -115,10 +115,9 @@ int get_slot_info(struct slot_info *slots)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_info()
|
static void dump_info(int current_slot)
|
||||||
{
|
{
|
||||||
struct slot_info slots[2] = { { 0 } };
|
struct slot_info slots[2] = { { 0 } };
|
||||||
int current_slot = impl->getCurrentSlot();
|
|
||||||
|
|
||||||
get_slot_info(slots);
|
get_slot_info(slots);
|
||||||
|
|
||||||
@@ -135,7 +134,7 @@ void dump_info()
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int optflag;
|
int optflag;
|
||||||
int slot = -1;
|
int slot = -1, current_slot;
|
||||||
int rc;
|
int rc;
|
||||||
bool ignore_missing_bsg = false;
|
bool ignore_missing_bsg = false;
|
||||||
|
|
||||||
@@ -144,9 +143,15 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_slot = impl->getCurrentSlot();
|
||||||
|
if (current_slot < 0) {
|
||||||
|
fprintf(stderr, "No slots found, is this an A/B device?\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (argc) {
|
switch (argc) {
|
||||||
case 1:
|
case 1:
|
||||||
dump_info();
|
dump_info(current_slot);
|
||||||
return 0;
|
return 0;
|
||||||
case 2:
|
case 2:
|
||||||
break;
|
break;
|
||||||
@@ -157,14 +162,13 @@ int main(int argc, char **argv)
|
|||||||
return usage();
|
return usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot < 0)
|
|
||||||
slot = impl->getCurrentSlot();
|
|
||||||
|
|
||||||
optflag = getopt(argc, argv, "hcmas:ub:n:x");
|
optflag = getopt(argc, argv, "hcmas:ub:n:x");
|
||||||
|
|
||||||
|
if (slot < 0 || optflag == 'c')
|
||||||
|
slot = current_slot;
|
||||||
|
|
||||||
switch (optflag) {
|
switch (optflag) {
|
||||||
case 'c':
|
case 'c':
|
||||||
slot = impl->getCurrentSlot();
|
|
||||||
printf("Current slot: %s\n", impl->getSuffix(slot));
|
printf("Current slot: %s\n", impl->getSuffix(slot));
|
||||||
return 0;
|
return 0;
|
||||||
case 'a':
|
case 'a':
|
||||||
|
|||||||
Reference in New Issue
Block a user