123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524 |
- #define _LARGEFILE64_SOURCE
- #include <stdio.h>
- #include <fcntl.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <sys/ioctl.h>
- #include <unistd.h>
- #include <linux/fs.h>
- #include <limits.h>
- #include <dirent.h>
- #include <linux/kernel.h>
- #include <asm/byteorder.h>
- #include <map>
- #include <vector>
- #include <string>
- #ifndef __STDC_FORMAT_MACROS
- #define __STDC_FORMAT_MACROS
- #endif
- #include <inttypes.h>
- #define LOG_TAG "gpt-utils"
- #include <cutils/log.h>
- #include <cutils/properties.h>
- #include "gpt-utils.h"
- #include <zlib.h>
- #include <endian.h>
- #define BLK_DEV_FILE "/dev/block/mmcblk0"
- #define BAK_PTN_NAME_EXT "bak"
- #define XBL_PRIMARY "/dev/block/bootdevice/by-name/xbl"
- #define XBL_BACKUP "/dev/block/bootdevice/by-name/xblbak"
- #define XBL_AB_PRIMARY "/dev/block/bootdevice/by-name/xbl_a"
- #define XBL_AB_SECONDARY "/dev/block/bootdevice/by-name/xbl_b"
- #define MAX_LUNS 26
- #define PATH_TRUNCATE_LOC (sizeof("/dev/block/sda") - 1)
- #define LUN_NAME_START_LOC (sizeof("/dev/block/") - 1)
- #define BOOT_LUN_A_ID 1
- #define BOOT_LUN_B_ID 2
- #define GET_4_BYTES(ptr) ((uint32_t) *((uint8_t *)(ptr)) | \
- ((uint32_t) *((uint8_t *)(ptr) + 1) << 8) | \
- ((uint32_t) *((uint8_t *)(ptr) + 2) << 16) | \
- ((uint32_t) *((uint8_t *)(ptr) + 3) << 24))
- #define GET_8_BYTES(ptr) ((uint64_t) *((uint8_t *)(ptr)) | \
- ((uint64_t) *((uint8_t *)(ptr) + 1) << 8) | \
- ((uint64_t) *((uint8_t *)(ptr) + 2) << 16) | \
- ((uint64_t) *((uint8_t *)(ptr) + 3) << 24) | \
- ((uint64_t) *((uint8_t *)(ptr) + 4) << 32) | \
- ((uint64_t) *((uint8_t *)(ptr) + 5) << 40) | \
- ((uint64_t) *((uint8_t *)(ptr) + 6) << 48) | \
- ((uint64_t) *((uint8_t *)(ptr) + 7) << 56))
- #define PUT_4_BYTES(ptr, y) *((uint8_t *)(ptr)) = (y) & 0xff; \
- *((uint8_t *)(ptr) + 1) = ((y) >> 8) & 0xff; \
- *((uint8_t *)(ptr) + 2) = ((y) >> 16) & 0xff; \
- *((uint8_t *)(ptr) + 3) = ((y) >> 24) & 0xff;
- using namespace std;
- enum gpt_state {
- GPT_OK = 0,
- GPT_BAD_SIGNATURE,
- GPT_BAD_CRC
- };
- struct update_data {
- char lun_list[MAX_LUNS][PATH_MAX];
- uint32_t num_valid_entries;
- };
- int32_t set_boot_lun(char *sg_dev,uint8_t boot_lun_id);
- static int blk_rw(int fd, int rw, int64_t offset, uint8_t *buf, unsigned len)
- {
- int r;
- if (lseek64(fd, offset, SEEK_SET) < 0) {
- fprintf(stderr, "block dev lseek64 %" PRIi64 " failed: %s\n", offset,
- strerror(errno));
- return -1;
- }
- if (rw)
- r = write(fd, buf, len);
- else
- r = read(fd, buf, len);
- if (r < 0)
- fprintf(stderr, "block dev %s failed: %s\n", rw ? "write" : "read",
- strerror(errno));
- else
- r = 0;
- return r;
- }
- static uint8_t *gpt_pentry_seek(const char *ptn_name,
- const uint8_t *pentries_start,
- const uint8_t *pentries_end,
- uint32_t pentry_size)
- {
- char *pentry_name;
- unsigned len = strlen(ptn_name);
- unsigned i;
- char name8[MAX_GPT_NAME_SIZE] = {0};
- for (pentry_name = (char *) (pentries_start + PARTITION_NAME_OFFSET);
- pentry_name < (char *) pentries_end;
- pentry_name += pentry_size) {
-
- for (i = 0; i < sizeof(name8) / 2; i++)
- name8[i] = pentry_name[i * 2];
- name8[i] = '\0';
- if (!strncmp(ptn_name, name8, len)) {
- if (name8[len] == 0 || !strcmp(&name8[len], BAK_PTN_NAME_EXT))
- return (uint8_t *) (pentry_name - PARTITION_NAME_OFFSET);
- }
- }
- return NULL;
- }
- static int gpt_boot_chain_swap(const uint8_t *pentries_start,
- const uint8_t *pentries_end,
- uint32_t pentry_size)
- {
- const char ptn_swap_list[][MAX_GPT_NAME_SIZE] = { PTN_SWAP_LIST };
- int backup_not_found = 1;
- unsigned i;
- for (i = 0; i < ARRAY_SIZE(ptn_swap_list); i++) {
- uint8_t *ptn_entry;
- uint8_t *ptn_bak_entry;
- uint8_t ptn_swap[PTN_ENTRY_SIZE];
-
-
- if (gpt_utils_is_ufs_device() && !strncmp(ptn_swap_list[i],PTN_XBL,strlen(PTN_XBL))
- || !strncmp(ptn_swap_list[i],PTN_MULTIIMGOEM,strlen(PTN_MULTIIMGOEM))
- || !strncmp(ptn_swap_list[i],PTN_MULTIIMGQTI,strlen(PTN_MULTIIMGQTI)))
- continue;
- ptn_entry = gpt_pentry_seek(ptn_swap_list[i], pentries_start,
- pentries_end, pentry_size);
- if (ptn_entry == NULL)
- continue;
- ptn_bak_entry = gpt_pentry_seek(ptn_swap_list[i],
- ptn_entry + pentry_size, pentries_end, pentry_size);
- if (ptn_bak_entry == NULL) {
- fprintf(stderr, "'%s' partition not backup - skip safe update\n",
- ptn_swap_list[i]);
- continue;
- }
-
- memcpy(ptn_swap, ptn_entry, PTN_ENTRY_SIZE);
- memcpy(ptn_entry, ptn_bak_entry, PTN_ENTRY_SIZE);
- memcpy(ptn_bak_entry, ptn_swap, PTN_ENTRY_SIZE);
- backup_not_found = 0;
- }
- return backup_not_found;
- }
- static int gpt2_set_boot_chain(int fd, enum boot_chain boot)
- {
- int64_t gpt2_header_offset;
- uint64_t pentries_start_offset;
- uint32_t gpt_header_size;
- uint32_t pentry_size;
- uint32_t pentries_array_size;
- uint8_t *gpt_header = NULL;
- uint8_t *pentries = NULL;
- uint32_t crc;
- uint32_t crc_zero;
- uint32_t blk_size = 0;
- int r;
- crc_zero = crc32(0L, Z_NULL, 0);
- if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
- fprintf(stderr, "Failed to get GPT device block size: %s\n",
- strerror(errno));
- r = -1;
- goto EXIT;
- }
- gpt_header = (uint8_t*)malloc(blk_size);
- if (!gpt_header) {
- fprintf(stderr, "Failed to allocate memory to hold GPT block\n");
- r = -1;
- goto EXIT;
- }
- gpt2_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
- if (gpt2_header_offset < 0) {
- fprintf(stderr, "Getting secondary GPT header offset failed: %s\n",
- strerror(errno));
- r = -1;
- goto EXIT;
- }
-
- r = blk_rw(fd, 0, blk_size, gpt_header, blk_size);
- if (r) {
- fprintf(stderr, "Failed to read primary GPT header from blk dev\n");
- goto EXIT;
- }
- pentries_start_offset =
- GET_8_BYTES(gpt_header + PENTRIES_OFFSET) * blk_size;
- pentry_size = GET_4_BYTES(gpt_header + PENTRY_SIZE_OFFSET);
- pentries_array_size =
- GET_4_BYTES(gpt_header + PARTITION_COUNT_OFFSET) * pentry_size;
- pentries = (uint8_t *) calloc(1, pentries_array_size);
- if (pentries == NULL) {
- fprintf(stderr,
- "Failed to alloc memory for GPT partition entries array\n");
- r = -1;
- goto EXIT;
- }
-
- r = blk_rw(fd, 0, pentries_start_offset, pentries, pentries_array_size);
- if (r)
- goto EXIT;
- crc = crc32(crc_zero, pentries, pentries_array_size);
- if (GET_4_BYTES(gpt_header + PARTITION_CRC_OFFSET) != crc) {
- fprintf(stderr, "Primary GPT partition entries array CRC invalid\n");
- r = -1;
- goto EXIT;
- }
-
- r = blk_rw(fd, 0, gpt2_header_offset, gpt_header, blk_size);
- if (r)
- goto EXIT;
- gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
- pentries_start_offset =
- GET_8_BYTES(gpt_header + PENTRIES_OFFSET) * blk_size;
- if (boot == BACKUP_BOOT) {
- r = gpt_boot_chain_swap(pentries, pentries + pentries_array_size,
- pentry_size);
- if (r)
- goto EXIT;
- }
- crc = crc32(crc_zero, pentries, pentries_array_size);
- PUT_4_BYTES(gpt_header + PARTITION_CRC_OFFSET, crc);
-
- PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
- crc = crc32(crc_zero, gpt_header, gpt_header_size);
- PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, crc);
-
- r = blk_rw(fd, 1, gpt2_header_offset, gpt_header, blk_size);
- if (!r)
-
- r = blk_rw(fd, 1, pentries_start_offset, pentries,
- pentries_array_size);
- EXIT:
- if(gpt_header)
- free(gpt_header);
- if (pentries)
- free(pentries);
- return r;
- }
- static int gpt_get_state(int fd, enum gpt_instance gpt, enum gpt_state *state)
- {
- int64_t gpt_header_offset;
- uint32_t gpt_header_size;
- uint8_t *gpt_header = NULL;
- uint32_t crc;
- uint32_t crc_zero;
- uint32_t blk_size = 0;
- *state = GPT_OK;
- crc_zero = crc32(0L, Z_NULL, 0);
- if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
- fprintf(stderr, "Failed to get GPT device block size: %s\n",
- strerror(errno));
- goto error;
- }
- gpt_header = (uint8_t*)malloc(blk_size);
- if (!gpt_header) {
- fprintf(stderr, "gpt_get_state:Failed to alloc memory for header\n");
- goto error;
- }
- if (gpt == PRIMARY_GPT)
- gpt_header_offset = blk_size;
- else {
- gpt_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
- if (gpt_header_offset < 0) {
- fprintf(stderr, "gpt_get_state:Seek to end of GPT part fail\n");
- goto error;
- }
- }
- if (blk_rw(fd, 0, gpt_header_offset, gpt_header, blk_size)) {
- fprintf(stderr, "gpt_get_state: blk_rw failed\n");
- goto error;
- }
- if (memcmp(gpt_header, GPT_SIGNATURE, sizeof(GPT_SIGNATURE)))
- *state = GPT_BAD_SIGNATURE;
- gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
- crc = GET_4_BYTES(gpt_header + HEADER_CRC_OFFSET);
-
- PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
- if (crc32(crc_zero, gpt_header, gpt_header_size) != crc)
- *state = GPT_BAD_CRC;
- free(gpt_header);
- return 0;
- error:
- if (gpt_header)
- free(gpt_header);
- return -1;
- }
- static int gpt_set_state(int fd, enum gpt_instance gpt, enum gpt_state state)
- {
- int64_t gpt_header_offset;
- uint32_t gpt_header_size;
- uint8_t *gpt_header = NULL;
- uint32_t crc;
- uint32_t crc_zero;
- uint32_t blk_size = 0;
- crc_zero = crc32(0L, Z_NULL, 0);
- if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
- fprintf(stderr, "Failed to get GPT device block size: %s\n",
- strerror(errno));
- goto error;
- }
- gpt_header = (uint8_t*)malloc(blk_size);
- if (!gpt_header) {
- fprintf(stderr, "Failed to alloc memory for gpt header\n");
- goto error;
- }
- if (gpt == PRIMARY_GPT)
- gpt_header_offset = blk_size;
- else {
- gpt_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
- if (gpt_header_offset < 0) {
- fprintf(stderr, "Failed to seek to end of GPT device\n");
- goto error;
- }
- }
- if (blk_rw(fd, 0, gpt_header_offset, gpt_header, blk_size)) {
- fprintf(stderr, "Failed to r/w gpt header\n");
- goto error;
- }
- if (state == GPT_OK)
- memcpy(gpt_header, GPT_SIGNATURE, sizeof(GPT_SIGNATURE));
- else if (state == GPT_BAD_SIGNATURE)
- *gpt_header = 0;
- else {
- fprintf(stderr, "gpt_set_state: Invalid state\n");
- goto error;
- }
- gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
-
- PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
- crc = crc32(crc_zero, gpt_header, gpt_header_size);
- PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, crc);
- if (blk_rw(fd, 1, gpt_header_offset, gpt_header, blk_size)) {
- fprintf(stderr, "gpt_set_state: blk write failed\n");
- goto error;
- }
- return 0;
- error:
- if(gpt_header)
- free(gpt_header);
- return -1;
- }
- int get_scsi_node_from_bootdevice(const char *bootdev_path,
- char *sg_node_path,
- size_t buf_size)
- {
- char sg_dir_path[PATH_MAX] = {0};
- char real_path[PATH_MAX] = {0};
- DIR *scsi_dir = NULL;
- struct dirent *de;
- int node_found = 0;
- if (!bootdev_path || !sg_node_path) {
- fprintf(stderr, "%s : invalid argument\n",
- __func__);
- goto error;
- }
- if (readlink(bootdev_path, real_path, sizeof(real_path) - 1) < 0) {
- fprintf(stderr, "failed to resolve link for %s(%s)\n",
- bootdev_path,
- strerror(errno));
- goto error;
- }
- if(strlen(real_path) < PATH_TRUNCATE_LOC + 1){
- fprintf(stderr, "Unrecognized path :%s:\n",
- real_path);
- goto error;
- }
-
-
- real_path[PATH_TRUNCATE_LOC] = '\0';
- if(strlen(real_path) < LUN_NAME_START_LOC + 1){
- fprintf(stderr, "Unrecognized truncated path :%s:\n",
- real_path);
- goto error;
- }
-
-
-
- snprintf(sg_dir_path, sizeof(sg_dir_path) - 1,
- "/sys/block/%s/device/scsi_generic",
- &real_path[LUN_NAME_START_LOC]);
- scsi_dir = opendir(sg_dir_path);
- if (!scsi_dir) {
- fprintf(stderr, "%s : Failed to open %s(%s)\n",
- __func__,
- sg_dir_path,
- strerror(errno));
- goto error;
- }
- while((de = readdir(scsi_dir))) {
- if (de->d_name[0] == '.')
- continue;
- else if (!strncmp(de->d_name, "sg", 2)) {
- snprintf(sg_node_path,
- buf_size -1,
- "/dev/%s",
- de->d_name);
- fprintf(stderr, "%s:scsi generic node is :%s:\n",
- __func__,
- sg_node_path);
- node_found = 1;
- break;
- }
- }
- if(!node_found) {
- fprintf(stderr,"%s: Unable to locate scsi generic node\n",
- __func__);
- goto error;
- }
- closedir(scsi_dir);
- return 0;
- error:
- if (scsi_dir)
- closedir(scsi_dir);
- return -1;
- }
- int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
- {
- struct stat st;
-
- char sg_dev_node[PATH_MAX] = {0};
- uint8_t boot_lun_id = 0;
- const char *boot_dev = NULL;
- if (chain == BACKUP_BOOT) {
- boot_lun_id = BOOT_LUN_B_ID;
- if (!stat(XBL_BACKUP, &st))
- boot_dev = XBL_BACKUP;
- else if (!stat(XBL_AB_SECONDARY, &st))
- boot_dev = XBL_AB_SECONDARY;
- else {
- fprintf(stderr, "%s: Failed to locate secondary xbl\n",
- __func__);
- goto error;
- }
- } else if (chain == NORMAL_BOOT) {
- boot_lun_id = BOOT_LUN_A_ID;
- if (!stat(XBL_PRIMARY, &st))
- boot_dev = XBL_PRIMARY;
- else if (!stat(XBL_AB_PRIMARY, &st))
- boot_dev = XBL_AB_PRIMARY;
- else {
- fprintf(stderr, "%s: Failed to locate primary xbl\n",
- __func__);
- goto error;
- }
- } else {
- fprintf(stderr, "%s: Invalid boot chain id\n", __func__);
- goto error;
- }
-
-
- 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;
- }
- fprintf(stderr, "%s: setting %s lun as boot lun\n",
- __func__,
- boot_dev);
- if (get_scsi_node_from_bootdevice(boot_dev,
- sg_dev_node,
- sizeof(sg_dev_node))) {
- fprintf(stderr, "%s: Failed to get scsi node path for xblbak\n",
- __func__);
- goto error;
- }
-
- if (set_boot_lun(sg_dev_node, boot_lun_id)) {
- fprintf(stderr, "%s: Failed to set xblbak as boot partition\n",
- __func__);
- goto error;
- }
- return 0;
- error:
- return -1;
- }
- int gpt_utils_is_ufs_device()
- {
- char bootdevice[PROPERTY_VALUE_MAX] = {0};
- property_get("ro.boot.bootdevice", bootdevice, "N/A");
- if (strlen(bootdevice) < strlen(".ufshc") + 1)
- return 0;
- return (!strncmp(&bootdevice[strlen(bootdevice) - strlen(".ufshc")],
- ".ufshc",
- sizeof(".ufshc")));
- }
- int prepare_partitions(enum boot_update_stage stage, const char *dev_path)
- {
- int r = 0;
- int fd = -1;
- int is_ufs = gpt_utils_is_ufs_device();
- enum gpt_state gpt_prim, gpt_second;
- enum boot_update_stage internal_stage;
- struct stat xbl_partition_stat;
- struct stat ufs_dir_stat;
- if (!dev_path) {
- fprintf(stderr, "%s: Invalid dev_path\n",
- __func__);
- r = -1;
- goto EXIT;
- }
- fd = open(dev_path, O_RDWR);
- if (fd < 0) {
- fprintf(stderr, "%s: Opening '%s' failed: %s\n",
- __func__,
- BLK_DEV_FILE,
- strerror(errno));
- r = -1;
- goto EXIT;
- }
- r = gpt_get_state(fd, PRIMARY_GPT, &gpt_prim) ||
- gpt_get_state(fd, SECONDARY_GPT, &gpt_second);
- if (r) {
- fprintf(stderr, "%s: Getting GPT headers state failed\n",
- __func__);
- goto EXIT;
- }
-
- if (gpt_prim == GPT_BAD_CRC || gpt_second == GPT_BAD_CRC) {
- fprintf(stderr, "%s: GPT headers CRC corruption detected, aborting\n",
- __func__);
- r = -1;
- goto EXIT;
- }
- if (gpt_prim == GPT_BAD_SIGNATURE && gpt_second == GPT_BAD_SIGNATURE) {
- fprintf(stderr, "%s: Both GPT headers corrupted, aborting\n",
- __func__);
- r = -1;
- goto EXIT;
- }
-
- if (gpt_prim == GPT_OK && gpt_second == GPT_OK)
- internal_stage = UPDATE_MAIN;
- else if (gpt_prim == GPT_BAD_SIGNATURE)
- internal_stage = UPDATE_BACKUP;
- else if (gpt_second == GPT_BAD_SIGNATURE)
- internal_stage = UPDATE_FINALIZE;
- else {
- fprintf(stderr, "%s: Abnormal GPTs state: primary (%d), secondary (%d), "
- "aborting\n", __func__, gpt_prim, gpt_second);
- r = -1;
- goto EXIT;
- }
-
- if ((int) stage == (int) internal_stage - 1)
- goto EXIT;
-
- if (stage != internal_stage) {
- r = -1;
- goto EXIT;
- }
- switch (stage) {
- case UPDATE_MAIN:
- if (is_ufs) {
- if(stat(XBL_PRIMARY, &xbl_partition_stat)||
- stat(XBL_BACKUP, &xbl_partition_stat)){
-
-
-
- fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
- __func__,
- strerror(errno));
- } else {
-
- r = gpt_utils_set_xbl_boot_partition(BACKUP_BOOT);
- if(r){
- fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
- __func__);
- goto EXIT;
- }
- }
- }
-
-
- fprintf(stderr, "%s: Preparing for primary partition update\n",
- __func__);
- r = gpt2_set_boot_chain(fd, BACKUP_BOOT);
- if (r) {
- if (r < 0)
- fprintf(stderr,
- "%s: Setting secondary GPT to backup boot failed\n",
- __func__);
-
- else
- r = 0;
- goto EXIT;
- }
-
-
- r = gpt_set_state(fd, PRIMARY_GPT, GPT_BAD_SIGNATURE);
- if (r) {
- fprintf(stderr, "%s: Corrupting primary GPT header failed\n",
- __func__);
- goto EXIT;
- }
- break;
- case UPDATE_BACKUP:
- if (is_ufs) {
- if(stat(XBL_PRIMARY, &xbl_partition_stat)||
- stat(XBL_BACKUP, &xbl_partition_stat)){
-
-
-
- fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
- __func__,
- strerror(errno));
- } else {
-
- r = gpt_utils_set_xbl_boot_partition(NORMAL_BOOT);
- if(r) {
- fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
- __func__);
- goto EXIT;
- }
- }
- }
-
- fprintf(stderr, "%s: Preparing for backup partition update\n",
- __func__);
- r = gpt_set_state(fd, PRIMARY_GPT, GPT_OK);
- if (r) {
- fprintf(stderr, "%s: Fixing primary GPT header failed\n",
- __func__);
- goto EXIT;
- }
-
- r = gpt_set_state(fd, SECONDARY_GPT, GPT_BAD_SIGNATURE);
- if (r) {
- fprintf(stderr, "%s: Corrupting secondary GPT header failed\n",
- __func__);
- goto EXIT;
- }
- break;
- case UPDATE_FINALIZE:
-
-
-
- fprintf(stderr, "%s: Finalizing partitions\n",
- __func__);
- r = gpt2_set_boot_chain(fd, NORMAL_BOOT);
- if (r < 0) {
- fprintf(stderr, "%s: Setting secondary GPT to normal boot failed\n",
- __func__);
- goto EXIT;
- }
- r = gpt_set_state(fd, SECONDARY_GPT, GPT_OK);
- if (r) {
- fprintf(stderr, "%s: Fixing secondary GPT header failed\n",
- __func__);
- goto EXIT;
- }
- break;
- default:;
- }
- EXIT:
- if (fd >= 0) {
- fsync(fd);
- close(fd);
- }
- return r;
- }
- int add_lun_to_update_list(char *lun_path, struct update_data *dat)
- {
- uint32_t i = 0;
- struct stat st;
- if (!lun_path || !dat){
- fprintf(stderr, "%s: Invalid data",
- __func__);
- return -1;
- }
- if (stat(lun_path, &st)) {
- fprintf(stderr, "%s: Unable to access %s. Skipping adding to list",
- __func__,
- lun_path);
- return -1;
- }
- if (dat->num_valid_entries == 0) {
- fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
- __func__,
- lun_path,
- i);
- strlcpy(dat->lun_list[0], lun_path,
- PATH_MAX * sizeof(char));
- dat->num_valid_entries = 1;
- } else {
- for (i = 0; (i < dat->num_valid_entries) &&
- (dat->num_valid_entries < MAX_LUNS - 1); i++) {
-
-
- if (!strncmp(lun_path,dat->lun_list[i],
- strlen(dat->lun_list[i]))) {
-
- return 0;
- }
- }
- fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
- __func__,
- lun_path,
- dat->num_valid_entries);
-
- strlcpy(dat->lun_list[dat->num_valid_entries], lun_path,
- PATH_MAX * sizeof(char));
- dat->num_valid_entries++;
- }
- return 0;
- }
- int prepare_boot_update(enum boot_update_stage stage)
- {
- int r, fd;
- int is_ufs = gpt_utils_is_ufs_device();
- struct stat ufs_dir_stat;
- struct update_data data;
- int rcode = 0;
- uint32_t i = 0;
- int is_error = 0;
- const char ptn_swap_list[][MAX_GPT_NAME_SIZE] = { PTN_SWAP_LIST };
-
- char buf[PATH_MAX] = {0};
-
- char real_path[PATH_MAX] = {0};
- if (!is_ufs) {
-
- return prepare_partitions(stage, BLK_DEV_FILE);
- } else {
-
-
-
-
-
-
-
- fprintf(stderr, "%s: Running on a UFS device\n",
- __func__);
- memset(&data, '\0', sizeof(struct update_data));
- for (i=0; i < ARRAY_SIZE(ptn_swap_list); i++) {
-
-
-
-
- if (!strncmp(ptn_swap_list[i],PTN_XBL,strlen(PTN_XBL))
- || !strncmp(ptn_swap_list[i],PTN_MULTIIMGOEM,strlen(PTN_MULTIIMGOEM))
- || !strncmp(ptn_swap_list[i],PTN_MULTIIMGQTI,strlen(PTN_MULTIIMGQTI)))
- continue;
- snprintf(buf, sizeof(buf),
- "%s/%sbak",
- BOOT_DEV_DIR,
- ptn_swap_list[i]);
- if (stat(buf, &ufs_dir_stat)) {
- continue;
- }
- if (readlink(buf, real_path, sizeof(real_path) - 1) < 0)
- {
- fprintf(stderr, "%s: readlink error. Skipping %s",
- __func__,
- strerror(errno));
- } else {
- if(strlen(real_path) < PATH_TRUNCATE_LOC + 1){
- fprintf(stderr, "Unknown path.Skipping :%s:\n",
- real_path);
- } else {
- real_path[PATH_TRUNCATE_LOC] = '\0';
- add_lun_to_update_list(real_path, &data);
- }
- }
- memset(buf, '\0', sizeof(buf));
- memset(real_path, '\0', sizeof(real_path));
- }
- for (i=0; i < data.num_valid_entries; i++) {
- fprintf(stderr, "%s: Preparing %s for update stage %d\n",
- __func__,
- data.lun_list[i],
- stage);
- rcode = prepare_partitions(stage, data.lun_list[i]);
- if (rcode != 0)
- {
- fprintf(stderr, "%s: Failed to prepare %s.Continuing..\n",
- __func__,
- data.lun_list[i]);
- is_error = 1;
- }
- }
- }
- if (is_error)
- return -1;
- return 0;
- }
- static int get_dev_path_from_partition_name(const char *partname,
- char *buf,
- size_t buflen)
- {
- struct stat st;
- char path[PATH_MAX] = {0};
- if (!partname || !buf || buflen < ((PATH_TRUNCATE_LOC) + 1)) {
- ALOGE("%s: Invalid argument", __func__);
- goto error;
- }
- if (gpt_utils_is_ufs_device()) {
-
- snprintf(path, sizeof(path),
- "%s/%s",
- BOOT_DEV_DIR,
- partname);
- if (stat(path, &st)) {
- goto error;
- }
- if (readlink(path, buf, buflen) < 0)
- {
- goto error;
- } else {
- buf[PATH_TRUNCATE_LOC] = '\0';
- }
- } else {
- snprintf(buf, buflen, BLK_DEV_FILE);
- }
- return 0;
- error:
- return -1;
- }
- int gpt_utils_get_partition_map(vector<string>& ptn_list,
- map<string, vector<string>>& partition_map) {
- char devpath[PATH_MAX] = {'\0'};
- map<string, vector<string>>::iterator it;
- if (ptn_list.size() < 1) {
- fprintf(stderr, "%s: Invalid ptn list\n", __func__);
- goto error;
- }
-
- for (uint32_t i = 0; i < ptn_list.size(); i++)
- {
-
-
- if (get_dev_path_from_partition_name(ptn_list[i].c_str(),
- devpath,
- sizeof(devpath))) {
-
-
- continue;
- }
- string path = devpath;
- it = partition_map.find(path);
- if (it != partition_map.end()) {
- it->second.push_back(ptn_list[i]);
- } else {
- vector<string> str_vec;
- str_vec.push_back( ptn_list[i]);
- partition_map.insert(pair<string, vector<string>>
- (path, str_vec));
- }
- memset(devpath, '\0', sizeof(devpath));
- }
- return 0;
- error:
- return -1;
- }
- static uint32_t gpt_get_block_size(int fd)
- {
- uint32_t block_size = 0;
- if (fd < 0) {
- ALOGE("%s: invalid descriptor",
- __func__);
- goto error;
- }
- if (ioctl(fd, BLKSSZGET, &block_size) != 0) {
- ALOGE("%s: Failed to get GPT dev block size : %s",
- __func__,
- strerror(errno));
- goto error;
- }
- return block_size;
- error:
- return 0;
- }
- static int gpt_set_header(uint8_t *gpt_header, int fd,
- enum gpt_instance instance)
- {
- uint32_t block_size = 0;
- off64_t gpt_header_offset = 0;
- if (!gpt_header || fd < 0) {
- ALOGE("%s: Invalid arguments",
- __func__);
- goto error;
- }
- block_size = gpt_get_block_size(fd);
- if (block_size == 0) {
- ALOGE("%s: Failed to get block size", __func__);
- goto error;
- }
- 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) {
- ALOGE("%s: Failed to get gpt header offset",__func__);
- goto error;
- }
- if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) {
- ALOGE("%s: Failed to write back GPT header", __func__);
- goto error;
- }
- return 0;
- error:
- return -1;
- }
- static uint8_t* gpt_get_header(const char *partname, enum gpt_instance instance)
- {
- uint8_t* hdr = NULL;
- char devpath[PATH_MAX] = {0};
- int64_t hdr_offset = 0;
- uint32_t block_size = 0;
- int fd = -1;
- if (!partname) {
- ALOGE("%s: Invalid partition name", __func__);
- goto error;
- }
- if (get_dev_path_from_partition_name(partname, devpath, sizeof(devpath))
- != 0) {
- ALOGE("%s: Failed to resolve path for %s",
- __func__,
- partname);
- goto error;
- }
- fd = open(devpath, O_RDWR);
- if (fd < 0) {
- ALOGE("%s: Failed to open %s : %s",
- __func__,
- devpath,
- strerror(errno));
- goto error;
- }
- block_size = gpt_get_block_size(fd);
- if (block_size == 0)
- {
- ALOGE("%s: Failed to get gpt block size for %s",
- __func__,
- partname);
- goto error;
- }
- hdr = (uint8_t*)malloc(block_size);
- if (!hdr) {
- ALOGE("%s: Failed to allocate memory for gpt header",
- __func__);
- }
- if (instance == PRIMARY_GPT)
- hdr_offset = block_size;
- else {
- hdr_offset = lseek64(fd, 0, SEEK_END) - block_size;
- }
- if (hdr_offset < 0) {
- ALOGE("%s: Failed to get gpt header offset",
- __func__);
- goto error;
- }
- if (blk_rw(fd, 0, hdr_offset, hdr, block_size)) {
- ALOGE("%s: Failed to read GPT header from device",
- __func__);
- goto error;
- }
- close(fd);
- return hdr;
- error:
- if (fd >= 0)
- close(fd);
- if (hdr)
- free(hdr);
- return NULL;
- }
- static uint8_t* gpt_get_pentry_arr(uint8_t *hdr, int fd)
- {
- 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) {
- ALOGE("%s: Invalid header", __func__);
- goto error;
- }
- if (fd < 0) {
- ALOGE("%s: Invalid fd", __func__);
- goto error;
- }
- block_size = gpt_get_block_size(fd);
- if (!block_size) {
- ALOGE("%s: Failed to get gpt block size for",
- __func__);
- goto error;
- }
- 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) {
- ALOGE("%s: Failed to allocate memory for partition array",
- __func__);
- goto error;
- }
- rc = blk_rw(fd, 0,
- pentries_start,
- pentry_arr,
- pentries_arr_size);
- if (rc) {
- ALOGE("%s: Failed to read partition entry array",
- __func__);
- goto error;
- }
- return pentry_arr;
- error:
- if (pentry_arr)
- free(pentry_arr);
- return NULL;
- }
- static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t* arr)
- {
- uint32_t block_size = 0;
- uint64_t pentries_start = 0;
- uint32_t pentry_size = 0;
- uint32_t pentries_arr_size = 0;
- int rc = 0;
- if (!hdr || fd < 0 || !arr) {
- ALOGE("%s: Invalid argument", __func__);
- goto error;
- }
- block_size = gpt_get_block_size(fd);
- if (!block_size) {
- ALOGE("%s: Failed to get gpt block size for",
- __func__);
- goto error;
- }
- 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;
- rc = blk_rw(fd, 1,
- pentries_start,
- arr,
- pentries_arr_size);
- if (rc) {
- ALOGE("%s: Failed to read partition entry array",
- __func__);
- goto error;
- }
- return 0;
- error:
- return -1;
- }
- struct gpt_disk * gpt_disk_alloc()
- {
- struct gpt_disk *disk;
- disk = (struct gpt_disk *)malloc(sizeof(struct gpt_disk));
- if (!disk) {
- ALOGE("%s: Failed to allocate memory", __func__);
- goto end;
- }
- memset(disk, 0, sizeof(struct gpt_disk));
- end:
- return disk;
- }
- 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;
- }
- int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *dsk)
- {
- struct gpt_disk *disk = NULL;
- int fd = -1;
- uint32_t gpt_header_size = 0;
- uint32_t crc_zero;
- crc_zero = crc32(0L, Z_NULL, 0);
- if (!dsk || !dev) {
- ALOGE("%s: Invalid arguments", __func__);
- goto error;
- }
- disk = dsk;
- disk->hdr = gpt_get_header(dev, PRIMARY_GPT);
- if (!disk->hdr) {
- ALOGE("%s: Failed to get primary header", __func__);
- goto error;
- }
- gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
- disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
- disk->hdr_bak = gpt_get_header(dev, SECONDARY_GPT);
- if (!disk->hdr_bak) {
- ALOGE("%s: Failed to get backup header", __func__);
- goto error;
- }
- disk->hdr_bak_crc = crc32(crc_zero, disk->hdr_bak, gpt_header_size);
-
-
- if (get_dev_path_from_partition_name(dev,
- disk->devpath,
- sizeof(disk->devpath)) != 0) {
- ALOGE("%s: Failed to resolve path for %s",
- __func__,
- dev);
- goto error;
- }
- fd = open(disk->devpath, O_RDWR);
- if (fd < 0) {
- ALOGE("%s: Failed to open %s: %s",
- __func__,
- disk->devpath,
- strerror(errno));
- goto error;
- }
- disk->pentry_arr = gpt_get_pentry_arr(disk->hdr, fd);
- if (!disk->pentry_arr) {
- ALOGE("%s: Failed to obtain partition entry array",
- __func__);
- goto error;
- }
- disk->pentry_arr_bak = gpt_get_pentry_arr(disk->hdr_bak, fd);
- if (!disk->pentry_arr_bak) {
- ALOGE("%s: Failed to obtain backup partition entry array",
- __func__);
- goto error;
- }
- disk->pentry_size = GET_4_BYTES(disk->hdr + PENTRY_SIZE_OFFSET);
- disk->pentry_arr_size =
- GET_4_BYTES(disk->hdr + PARTITION_COUNT_OFFSET) *
- disk->pentry_size;
- disk->pentry_arr_crc = GET_4_BYTES(disk->hdr + 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);
- disk->is_initialized = GPT_DISK_INIT_MAGIC;
- return 0;
- error:
- if (fd >= 0)
- close(fd);
- return -1;
- }
- uint8_t* gpt_disk_get_pentry(struct gpt_disk *disk,
- const char *partname,
- enum gpt_instance instance)
- {
- uint8_t *ptn_arr = NULL;
- if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) {
- ALOGE("%s: Invalid argument",__func__);
- goto error;
- }
- ptn_arr = (instance == PRIMARY_GPT) ?
- disk->pentry_arr : disk->pentry_arr_bak;
- return (gpt_pentry_seek(partname, ptn_arr,
- ptn_arr + disk->pentry_arr_size ,
- disk->pentry_size));
- error:
- return NULL;
- }
- int gpt_disk_update_crc(struct gpt_disk *disk)
- {
- uint32_t gpt_header_size = 0;
- uint32_t crc_zero;
- crc_zero = crc32(0L, Z_NULL, 0);
- if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
- ALOGE("%s: invalid argument", __func__);
- goto error;
- }
-
- disk->pentry_arr_crc = crc32(crc_zero,
- disk->pentry_arr,
- disk->pentry_arr_size);
-
- disk->pentry_arr_bak_crc = crc32(crc_zero,
- disk->pentry_arr_bak,
- disk->pentry_arr_size);
-
- PUT_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET, disk->pentry_arr_crc);
-
- PUT_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET,
- disk->pentry_arr_bak_crc);
-
- gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
-
- PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, 0);
- PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, 0);
- disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
- disk->hdr_bak_crc = crc32(crc_zero, 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);
- return 0;
- error:
- return -1;
- }
- int gpt_disk_commit(struct gpt_disk *disk)
- {
- int fd = -1;
- if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)){
- ALOGE("%s: Invalid args", __func__);
- goto error;
- }
- fd = open(disk->devpath, O_RDWR | O_DSYNC);
- if (fd < 0) {
- ALOGE("%s: Failed to open %s: %s",
- __func__,
- disk->devpath,
- strerror(errno));
- goto error;
- }
-
- if(gpt_set_header(disk->hdr, fd, PRIMARY_GPT) != 0) {
- ALOGE("%s: Failed to update primary GPT header",
- __func__);
- goto error;
- }
-
- if (gpt_set_pentry_arr(disk->hdr, fd, disk->pentry_arr)) {
- ALOGE("%s: Failed to write primary GPT partition arr",
- __func__);
- goto error;
- }
-
- if(gpt_set_header(disk->hdr_bak, fd, SECONDARY_GPT) != 0) {
- ALOGE("%s: Failed to update secondary GPT header",
- __func__);
- goto error;
- }
-
- if (gpt_set_pentry_arr(disk->hdr_bak, fd, disk->pentry_arr_bak)) {
- ALOGE("%s: Failed to write secondary GPT partition arr",
- __func__);
- goto error;
- }
- fsync(fd);
- close(fd);
- return 0;
- error:
- if (fd >= 0)
- close(fd);
- return -1;
- }
|