12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520 |
- #define _LARGEFILE64_SOURCE
- #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 <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;
- 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 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;
- }
|