gpt-utils.cpp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524
  1. /*
  2. * Copyright (c) 2013,2016,2020 The Linux Foundation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above
  10. * copyright notice, this list of conditions and the following
  11. * disclaimer in the documentation and/or other materials provided
  12. * with the distribution.
  13. * * Neither the name of The Linux Foundation nor the names of its
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  21. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  24. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  26. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  27. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #define _LARGEFILE64_SOURCE /* enable lseek64() */
  30. /******************************************************************************
  31. * INCLUDE SECTION
  32. ******************************************************************************/
  33. #include <stdio.h>
  34. #include <fcntl.h>
  35. #include <string.h>
  36. #include <errno.h>
  37. #include <sys/stat.h>
  38. #include <sys/ioctl.h>
  39. #include <unistd.h>
  40. #include <linux/fs.h>
  41. #include <limits.h>
  42. #include <dirent.h>
  43. #include <linux/kernel.h>
  44. #include <asm/byteorder.h>
  45. #include <map>
  46. #include <vector>
  47. #include <string>
  48. #ifndef __STDC_FORMAT_MACROS
  49. #define __STDC_FORMAT_MACROS
  50. #endif
  51. #include <inttypes.h>
  52. #define LOG_TAG "gpt-utils"
  53. #include <cutils/log.h>
  54. #include <cutils/properties.h>
  55. #include "gpt-utils.h"
  56. #include <zlib.h>
  57. #include <endian.h>
  58. /******************************************************************************
  59. * DEFINE SECTION
  60. ******************************************************************************/
  61. #define BLK_DEV_FILE "/dev/block/mmcblk0"
  62. /* list the names of the backed-up partitions to be swapped */
  63. /* extension used for the backup partitions - tzbak, abootbak, etc. */
  64. #define BAK_PTN_NAME_EXT "bak"
  65. #define XBL_PRIMARY "/dev/block/bootdevice/by-name/xbl"
  66. #define XBL_BACKUP "/dev/block/bootdevice/by-name/xblbak"
  67. #define XBL_AB_PRIMARY "/dev/block/bootdevice/by-name/xbl_a"
  68. #define XBL_AB_SECONDARY "/dev/block/bootdevice/by-name/xbl_b"
  69. /* GPT defines */
  70. #define MAX_LUNS 26
  71. //This will allow us to get the root lun path from the path to the partition.
  72. //i.e: from /dev/block/sdaXXX get /dev/block/sda. The assumption here is that
  73. //the boot critical luns lie between sda to sdz which is acceptable because
  74. //only user added external disks,etc would lie beyond that limit which do not
  75. //contain partitions that interest us here.
  76. #define PATH_TRUNCATE_LOC (sizeof("/dev/block/sda") - 1)
  77. //From /dev/block/sda get just sda
  78. #define LUN_NAME_START_LOC (sizeof("/dev/block/") - 1)
  79. #define BOOT_LUN_A_ID 1
  80. #define BOOT_LUN_B_ID 2
  81. /******************************************************************************
  82. * MACROS
  83. ******************************************************************************/
  84. #define GET_4_BYTES(ptr) ((uint32_t) *((uint8_t *)(ptr)) | \
  85. ((uint32_t) *((uint8_t *)(ptr) + 1) << 8) | \
  86. ((uint32_t) *((uint8_t *)(ptr) + 2) << 16) | \
  87. ((uint32_t) *((uint8_t *)(ptr) + 3) << 24))
  88. #define GET_8_BYTES(ptr) ((uint64_t) *((uint8_t *)(ptr)) | \
  89. ((uint64_t) *((uint8_t *)(ptr) + 1) << 8) | \
  90. ((uint64_t) *((uint8_t *)(ptr) + 2) << 16) | \
  91. ((uint64_t) *((uint8_t *)(ptr) + 3) << 24) | \
  92. ((uint64_t) *((uint8_t *)(ptr) + 4) << 32) | \
  93. ((uint64_t) *((uint8_t *)(ptr) + 5) << 40) | \
  94. ((uint64_t) *((uint8_t *)(ptr) + 6) << 48) | \
  95. ((uint64_t) *((uint8_t *)(ptr) + 7) << 56))
  96. #define PUT_4_BYTES(ptr, y) *((uint8_t *)(ptr)) = (y) & 0xff; \
  97. *((uint8_t *)(ptr) + 1) = ((y) >> 8) & 0xff; \
  98. *((uint8_t *)(ptr) + 2) = ((y) >> 16) & 0xff; \
  99. *((uint8_t *)(ptr) + 3) = ((y) >> 24) & 0xff;
  100. /******************************************************************************
  101. * TYPES
  102. ******************************************************************************/
  103. using namespace std;
  104. enum gpt_state {
  105. GPT_OK = 0,
  106. GPT_BAD_SIGNATURE,
  107. GPT_BAD_CRC
  108. };
  109. //List of LUN's containing boot critical images.
  110. //Required in the case of UFS devices
  111. struct update_data {
  112. char lun_list[MAX_LUNS][PATH_MAX];
  113. uint32_t num_valid_entries;
  114. };
  115. int32_t set_boot_lun(char *sg_dev,uint8_t boot_lun_id);
  116. /******************************************************************************
  117. * FUNCTIONS
  118. ******************************************************************************/
  119. /**
  120. * ==========================================================================
  121. *
  122. * \brief Read/Write len bytes from/to block dev
  123. *
  124. * \param [in] fd block dev file descriptor (returned from open)
  125. * \param [in] rw RW flag: 0 - read, != 0 - write
  126. * \param [in] offset block dev offset [bytes] - RW start position
  127. * \param [in] buf Pointer to the buffer containing the data
  128. * \param [in] len RW size in bytes. Buf must be at least that big
  129. *
  130. * \return 0 on success
  131. *
  132. * ==========================================================================
  133. */
  134. static int blk_rw(int fd, int rw, int64_t offset, uint8_t *buf, unsigned len)
  135. {
  136. int r;
  137. if (lseek64(fd, offset, SEEK_SET) < 0) {
  138. fprintf(stderr, "block dev lseek64 %" PRIi64 " failed: %s\n", offset,
  139. strerror(errno));
  140. return -1;
  141. }
  142. if (rw)
  143. r = write(fd, buf, len);
  144. else
  145. r = read(fd, buf, len);
  146. if (r < 0)
  147. fprintf(stderr, "block dev %s failed: %s\n", rw ? "write" : "read",
  148. strerror(errno));
  149. else
  150. r = 0;
  151. return r;
  152. }
  153. /**
  154. * ==========================================================================
  155. *
  156. * \brief Search within GPT for partition entry with the given name
  157. * or it's backup twin (name-bak).
  158. *
  159. * \param [in] ptn_name Partition name to seek
  160. * \param [in] pentries_start Partition entries array start pointer
  161. * \param [in] pentries_end Partition entries array end pointer
  162. * \param [in] pentry_size Single partition entry size [bytes]
  163. *
  164. * \return First partition entry pointer that matches the name or NULL
  165. *
  166. * ==========================================================================
  167. */
  168. static uint8_t *gpt_pentry_seek(const char *ptn_name,
  169. const uint8_t *pentries_start,
  170. const uint8_t *pentries_end,
  171. uint32_t pentry_size)
  172. {
  173. char *pentry_name;
  174. unsigned len = strlen(ptn_name);
  175. unsigned i;
  176. char name8[MAX_GPT_NAME_SIZE] = {0}; // initialize with null
  177. for (pentry_name = (char *) (pentries_start + PARTITION_NAME_OFFSET);
  178. pentry_name < (char *) pentries_end;
  179. pentry_name += pentry_size) {
  180. /* Partition names in GPT are UTF-16 - ignoring UTF-16 2nd byte */
  181. for (i = 0; i < sizeof(name8) / 2; i++)
  182. name8[i] = pentry_name[i * 2];
  183. name8[i] = '\0';
  184. if (!strncmp(ptn_name, name8, len)) {
  185. if (name8[len] == 0 || !strcmp(&name8[len], BAK_PTN_NAME_EXT))
  186. return (uint8_t *) (pentry_name - PARTITION_NAME_OFFSET);
  187. }
  188. }
  189. return NULL;
  190. }
  191. /**
  192. * ==========================================================================
  193. *
  194. * \brief Swaps boot chain in GPT partition entries array
  195. *
  196. * \param [in] pentries_start Partition entries array start
  197. * \param [in] pentries_end Partition entries array end
  198. * \param [in] pentry_size Single partition entry size
  199. *
  200. * \return 0 on success, 1 if no backup partitions found
  201. *
  202. * ==========================================================================
  203. */
  204. static int gpt_boot_chain_swap(const uint8_t *pentries_start,
  205. const uint8_t *pentries_end,
  206. uint32_t pentry_size)
  207. {
  208. const char ptn_swap_list[][MAX_GPT_NAME_SIZE] = { PTN_SWAP_LIST };
  209. int backup_not_found = 1;
  210. unsigned i;
  211. for (i = 0; i < ARRAY_SIZE(ptn_swap_list); i++) {
  212. uint8_t *ptn_entry;
  213. uint8_t *ptn_bak_entry;
  214. uint8_t ptn_swap[PTN_ENTRY_SIZE];
  215. //Skip the xbl, multiimgoem, multiimgqti partitions on UFS devices. That is handled
  216. //seperately.
  217. if (gpt_utils_is_ufs_device() && !strncmp(ptn_swap_list[i],PTN_XBL,strlen(PTN_XBL))
  218. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGOEM,strlen(PTN_MULTIIMGOEM))
  219. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGQTI,strlen(PTN_MULTIIMGQTI)))
  220. continue;
  221. ptn_entry = gpt_pentry_seek(ptn_swap_list[i], pentries_start,
  222. pentries_end, pentry_size);
  223. if (ptn_entry == NULL)
  224. continue;
  225. ptn_bak_entry = gpt_pentry_seek(ptn_swap_list[i],
  226. ptn_entry + pentry_size, pentries_end, pentry_size);
  227. if (ptn_bak_entry == NULL) {
  228. fprintf(stderr, "'%s' partition not backup - skip safe update\n",
  229. ptn_swap_list[i]);
  230. continue;
  231. }
  232. /* swap primary <-> backup partition entries */
  233. memcpy(ptn_swap, ptn_entry, PTN_ENTRY_SIZE);
  234. memcpy(ptn_entry, ptn_bak_entry, PTN_ENTRY_SIZE);
  235. memcpy(ptn_bak_entry, ptn_swap, PTN_ENTRY_SIZE);
  236. backup_not_found = 0;
  237. }
  238. return backup_not_found;
  239. }
  240. /**
  241. * ==========================================================================
  242. *
  243. * \brief Sets secondary GPT boot chain
  244. *
  245. * \param [in] fd block dev file descriptor
  246. * \param [in] boot Boot chain to switch to
  247. *
  248. * \return 0 on success
  249. *
  250. * ==========================================================================
  251. */
  252. static int gpt2_set_boot_chain(int fd, enum boot_chain boot)
  253. {
  254. int64_t gpt2_header_offset;
  255. uint64_t pentries_start_offset;
  256. uint32_t gpt_header_size;
  257. uint32_t pentry_size;
  258. uint32_t pentries_array_size;
  259. uint8_t *gpt_header = NULL;
  260. uint8_t *pentries = NULL;
  261. uint32_t crc;
  262. uint32_t crc_zero;
  263. uint32_t blk_size = 0;
  264. int r;
  265. crc_zero = crc32(0L, Z_NULL, 0);
  266. if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
  267. fprintf(stderr, "Failed to get GPT device block size: %s\n",
  268. strerror(errno));
  269. r = -1;
  270. goto EXIT;
  271. }
  272. gpt_header = (uint8_t*)malloc(blk_size);
  273. if (!gpt_header) {
  274. fprintf(stderr, "Failed to allocate memory to hold GPT block\n");
  275. r = -1;
  276. goto EXIT;
  277. }
  278. gpt2_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
  279. if (gpt2_header_offset < 0) {
  280. fprintf(stderr, "Getting secondary GPT header offset failed: %s\n",
  281. strerror(errno));
  282. r = -1;
  283. goto EXIT;
  284. }
  285. /* Read primary GPT header from block dev */
  286. r = blk_rw(fd, 0, blk_size, gpt_header, blk_size);
  287. if (r) {
  288. fprintf(stderr, "Failed to read primary GPT header from blk dev\n");
  289. goto EXIT;
  290. }
  291. pentries_start_offset =
  292. GET_8_BYTES(gpt_header + PENTRIES_OFFSET) * blk_size;
  293. pentry_size = GET_4_BYTES(gpt_header + PENTRY_SIZE_OFFSET);
  294. pentries_array_size =
  295. GET_4_BYTES(gpt_header + PARTITION_COUNT_OFFSET) * pentry_size;
  296. pentries = (uint8_t *) calloc(1, pentries_array_size);
  297. if (pentries == NULL) {
  298. fprintf(stderr,
  299. "Failed to alloc memory for GPT partition entries array\n");
  300. r = -1;
  301. goto EXIT;
  302. }
  303. /* Read primary GPT partititon entries array from block dev */
  304. r = blk_rw(fd, 0, pentries_start_offset, pentries, pentries_array_size);
  305. if (r)
  306. goto EXIT;
  307. crc = crc32(crc_zero, pentries, pentries_array_size);
  308. if (GET_4_BYTES(gpt_header + PARTITION_CRC_OFFSET) != crc) {
  309. fprintf(stderr, "Primary GPT partition entries array CRC invalid\n");
  310. r = -1;
  311. goto EXIT;
  312. }
  313. /* Read secondary GPT header from block dev */
  314. r = blk_rw(fd, 0, gpt2_header_offset, gpt_header, blk_size);
  315. if (r)
  316. goto EXIT;
  317. gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
  318. pentries_start_offset =
  319. GET_8_BYTES(gpt_header + PENTRIES_OFFSET) * blk_size;
  320. if (boot == BACKUP_BOOT) {
  321. r = gpt_boot_chain_swap(pentries, pentries + pentries_array_size,
  322. pentry_size);
  323. if (r)
  324. goto EXIT;
  325. }
  326. crc = crc32(crc_zero, pentries, pentries_array_size);
  327. PUT_4_BYTES(gpt_header + PARTITION_CRC_OFFSET, crc);
  328. /* header CRC is calculated with this field cleared */
  329. PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
  330. crc = crc32(crc_zero, gpt_header, gpt_header_size);
  331. PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, crc);
  332. /* Write the modified GPT header back to block dev */
  333. r = blk_rw(fd, 1, gpt2_header_offset, gpt_header, blk_size);
  334. if (!r)
  335. /* Write the modified GPT partititon entries array back to block dev */
  336. r = blk_rw(fd, 1, pentries_start_offset, pentries,
  337. pentries_array_size);
  338. EXIT:
  339. if(gpt_header)
  340. free(gpt_header);
  341. if (pentries)
  342. free(pentries);
  343. return r;
  344. }
  345. /**
  346. * ==========================================================================
  347. *
  348. * \brief Checks GPT state (header signature and CRC)
  349. *
  350. * \param [in] fd block dev file descriptor
  351. * \param [in] gpt GPT header to be checked
  352. * \param [out] state GPT header state
  353. *
  354. * \return 0 on success
  355. *
  356. * ==========================================================================
  357. */
  358. static int gpt_get_state(int fd, enum gpt_instance gpt, enum gpt_state *state)
  359. {
  360. int64_t gpt_header_offset;
  361. uint32_t gpt_header_size;
  362. uint8_t *gpt_header = NULL;
  363. uint32_t crc;
  364. uint32_t crc_zero;
  365. uint32_t blk_size = 0;
  366. *state = GPT_OK;
  367. crc_zero = crc32(0L, Z_NULL, 0);
  368. if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
  369. fprintf(stderr, "Failed to get GPT device block size: %s\n",
  370. strerror(errno));
  371. goto error;
  372. }
  373. gpt_header = (uint8_t*)malloc(blk_size);
  374. if (!gpt_header) {
  375. fprintf(stderr, "gpt_get_state:Failed to alloc memory for header\n");
  376. goto error;
  377. }
  378. if (gpt == PRIMARY_GPT)
  379. gpt_header_offset = blk_size;
  380. else {
  381. gpt_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
  382. if (gpt_header_offset < 0) {
  383. fprintf(stderr, "gpt_get_state:Seek to end of GPT part fail\n");
  384. goto error;
  385. }
  386. }
  387. if (blk_rw(fd, 0, gpt_header_offset, gpt_header, blk_size)) {
  388. fprintf(stderr, "gpt_get_state: blk_rw failed\n");
  389. goto error;
  390. }
  391. if (memcmp(gpt_header, GPT_SIGNATURE, sizeof(GPT_SIGNATURE)))
  392. *state = GPT_BAD_SIGNATURE;
  393. gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
  394. crc = GET_4_BYTES(gpt_header + HEADER_CRC_OFFSET);
  395. /* header CRC is calculated with this field cleared */
  396. PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
  397. if (crc32(crc_zero, gpt_header, gpt_header_size) != crc)
  398. *state = GPT_BAD_CRC;
  399. free(gpt_header);
  400. return 0;
  401. error:
  402. if (gpt_header)
  403. free(gpt_header);
  404. return -1;
  405. }
  406. /**
  407. * ==========================================================================
  408. *
  409. * \brief Sets GPT header state (used to corrupt and fix GPT signature)
  410. *
  411. * \param [in] fd block dev file descriptor
  412. * \param [in] gpt GPT header to be checked
  413. * \param [in] state GPT header state to set (GPT_OK or GPT_BAD_SIGNATURE)
  414. *
  415. * \return 0 on success
  416. *
  417. * ==========================================================================
  418. */
  419. static int gpt_set_state(int fd, enum gpt_instance gpt, enum gpt_state state)
  420. {
  421. int64_t gpt_header_offset;
  422. uint32_t gpt_header_size;
  423. uint8_t *gpt_header = NULL;
  424. uint32_t crc;
  425. uint32_t crc_zero;
  426. uint32_t blk_size = 0;
  427. crc_zero = crc32(0L, Z_NULL, 0);
  428. if (ioctl(fd, BLKSSZGET, &blk_size) != 0) {
  429. fprintf(stderr, "Failed to get GPT device block size: %s\n",
  430. strerror(errno));
  431. goto error;
  432. }
  433. gpt_header = (uint8_t*)malloc(blk_size);
  434. if (!gpt_header) {
  435. fprintf(stderr, "Failed to alloc memory for gpt header\n");
  436. goto error;
  437. }
  438. if (gpt == PRIMARY_GPT)
  439. gpt_header_offset = blk_size;
  440. else {
  441. gpt_header_offset = lseek64(fd, 0, SEEK_END) - blk_size;
  442. if (gpt_header_offset < 0) {
  443. fprintf(stderr, "Failed to seek to end of GPT device\n");
  444. goto error;
  445. }
  446. }
  447. if (blk_rw(fd, 0, gpt_header_offset, gpt_header, blk_size)) {
  448. fprintf(stderr, "Failed to r/w gpt header\n");
  449. goto error;
  450. }
  451. if (state == GPT_OK)
  452. memcpy(gpt_header, GPT_SIGNATURE, sizeof(GPT_SIGNATURE));
  453. else if (state == GPT_BAD_SIGNATURE)
  454. *gpt_header = 0;
  455. else {
  456. fprintf(stderr, "gpt_set_state: Invalid state\n");
  457. goto error;
  458. }
  459. gpt_header_size = GET_4_BYTES(gpt_header + HEADER_SIZE_OFFSET);
  460. /* header CRC is calculated with this field cleared */
  461. PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, 0);
  462. crc = crc32(crc_zero, gpt_header, gpt_header_size);
  463. PUT_4_BYTES(gpt_header + HEADER_CRC_OFFSET, crc);
  464. if (blk_rw(fd, 1, gpt_header_offset, gpt_header, blk_size)) {
  465. fprintf(stderr, "gpt_set_state: blk write failed\n");
  466. goto error;
  467. }
  468. return 0;
  469. error:
  470. if(gpt_header)
  471. free(gpt_header);
  472. return -1;
  473. }
  474. int get_scsi_node_from_bootdevice(const char *bootdev_path,
  475. char *sg_node_path,
  476. size_t buf_size)
  477. {
  478. char sg_dir_path[PATH_MAX] = {0};
  479. char real_path[PATH_MAX] = {0};
  480. DIR *scsi_dir = NULL;
  481. struct dirent *de;
  482. int node_found = 0;
  483. if (!bootdev_path || !sg_node_path) {
  484. fprintf(stderr, "%s : invalid argument\n",
  485. __func__);
  486. goto error;
  487. }
  488. if (readlink(bootdev_path, real_path, sizeof(real_path) - 1) < 0) {
  489. fprintf(stderr, "failed to resolve link for %s(%s)\n",
  490. bootdev_path,
  491. strerror(errno));
  492. goto error;
  493. }
  494. if(strlen(real_path) < PATH_TRUNCATE_LOC + 1){
  495. fprintf(stderr, "Unrecognized path :%s:\n",
  496. real_path);
  497. goto error;
  498. }
  499. //For the safe side in case there are additional partitions on
  500. //the XBL lun we truncate the name.
  501. real_path[PATH_TRUNCATE_LOC] = '\0';
  502. if(strlen(real_path) < LUN_NAME_START_LOC + 1){
  503. fprintf(stderr, "Unrecognized truncated path :%s:\n",
  504. real_path);
  505. goto error;
  506. }
  507. //This will give us /dev/block/sdb/device/scsi_generic
  508. //which contains a file sgY whose name gives us the path
  509. //to /dev/sgY which we return
  510. snprintf(sg_dir_path, sizeof(sg_dir_path) - 1,
  511. "/sys/block/%s/device/scsi_generic",
  512. &real_path[LUN_NAME_START_LOC]);
  513. scsi_dir = opendir(sg_dir_path);
  514. if (!scsi_dir) {
  515. fprintf(stderr, "%s : Failed to open %s(%s)\n",
  516. __func__,
  517. sg_dir_path,
  518. strerror(errno));
  519. goto error;
  520. }
  521. while((de = readdir(scsi_dir))) {
  522. if (de->d_name[0] == '.')
  523. continue;
  524. else if (!strncmp(de->d_name, "sg", 2)) {
  525. snprintf(sg_node_path,
  526. buf_size -1,
  527. "/dev/%s",
  528. de->d_name);
  529. fprintf(stderr, "%s:scsi generic node is :%s:\n",
  530. __func__,
  531. sg_node_path);
  532. node_found = 1;
  533. break;
  534. }
  535. }
  536. if(!node_found) {
  537. fprintf(stderr,"%s: Unable to locate scsi generic node\n",
  538. __func__);
  539. goto error;
  540. }
  541. closedir(scsi_dir);
  542. return 0;
  543. error:
  544. if (scsi_dir)
  545. closedir(scsi_dir);
  546. return -1;
  547. }
  548. //Swtich betwieen using either the primary or the backup
  549. //boot LUN for boot. This is required since UFS boot partitions
  550. //cannot have a backup GPT which is what we use for failsafe
  551. //updates of the other 'critical' partitions. This function will
  552. //not be invoked for emmc targets and on UFS targets is only required
  553. //to be invoked for XBL.
  554. //
  555. //The algorithm to do this is as follows:
  556. //- Find the real block device(eg: /dev/block/sdb) that corresponds
  557. // to the /dev/block/bootdevice/by-name/xbl(bak) symlink
  558. //
  559. //- Once we have the block device 'node' name(sdb in the above example)
  560. // use this node to to locate the scsi generic device that represents
  561. // it by checking the file /sys/block/sdb/device/scsi_generic/sgY
  562. //
  563. //- Once we locate sgY we call the query ioctl on /dev/sgy to switch
  564. //the boot lun to either LUNA or LUNB
  565. int gpt_utils_set_xbl_boot_partition(enum boot_chain chain)
  566. {
  567. struct stat st;
  568. ///sys/block/sdX/device/scsi_generic/
  569. char sg_dev_node[PATH_MAX] = {0};
  570. uint8_t boot_lun_id = 0;
  571. const char *boot_dev = NULL;
  572. if (chain == BACKUP_BOOT) {
  573. boot_lun_id = BOOT_LUN_B_ID;
  574. if (!stat(XBL_BACKUP, &st))
  575. boot_dev = XBL_BACKUP;
  576. else if (!stat(XBL_AB_SECONDARY, &st))
  577. boot_dev = XBL_AB_SECONDARY;
  578. else {
  579. fprintf(stderr, "%s: Failed to locate secondary xbl\n",
  580. __func__);
  581. goto error;
  582. }
  583. } else if (chain == NORMAL_BOOT) {
  584. boot_lun_id = BOOT_LUN_A_ID;
  585. if (!stat(XBL_PRIMARY, &st))
  586. boot_dev = XBL_PRIMARY;
  587. else if (!stat(XBL_AB_PRIMARY, &st))
  588. boot_dev = XBL_AB_PRIMARY;
  589. else {
  590. fprintf(stderr, "%s: Failed to locate primary xbl\n",
  591. __func__);
  592. goto error;
  593. }
  594. } else {
  595. fprintf(stderr, "%s: Invalid boot chain id\n", __func__);
  596. goto error;
  597. }
  598. //We need either both xbl and xblbak or both xbl_a and xbl_b to exist at
  599. //the same time. If not the current configuration is invalid.
  600. if((stat(XBL_PRIMARY, &st) ||
  601. stat(XBL_BACKUP, &st)) &&
  602. (stat(XBL_AB_PRIMARY, &st) ||
  603. stat(XBL_AB_SECONDARY, &st))) {
  604. fprintf(stderr, "%s:primary/secondary XBL prt not found(%s)\n",
  605. __func__,
  606. strerror(errno));
  607. goto error;
  608. }
  609. fprintf(stderr, "%s: setting %s lun as boot lun\n",
  610. __func__,
  611. boot_dev);
  612. if (get_scsi_node_from_bootdevice(boot_dev,
  613. sg_dev_node,
  614. sizeof(sg_dev_node))) {
  615. fprintf(stderr, "%s: Failed to get scsi node path for xblbak\n",
  616. __func__);
  617. goto error;
  618. }
  619. /* set boot lun using /dev/sg or /dev/ufs-bsg* */
  620. if (set_boot_lun(sg_dev_node, boot_lun_id)) {
  621. fprintf(stderr, "%s: Failed to set xblbak as boot partition\n",
  622. __func__);
  623. goto error;
  624. }
  625. return 0;
  626. error:
  627. return -1;
  628. }
  629. int gpt_utils_is_ufs_device()
  630. {
  631. char bootdevice[PROPERTY_VALUE_MAX] = {0};
  632. property_get("ro.boot.bootdevice", bootdevice, "N/A");
  633. if (strlen(bootdevice) < strlen(".ufshc") + 1)
  634. return 0;
  635. return (!strncmp(&bootdevice[strlen(bootdevice) - strlen(".ufshc")],
  636. ".ufshc",
  637. sizeof(".ufshc")));
  638. }
  639. //dev_path is the path to the block device that contains the GPT image that
  640. //needs to be updated. This would be the device which holds one or more critical
  641. //boot partitions and their backups. In the case of EMMC this function would
  642. //be invoked only once on /dev/block/mmcblk1 since it holds the GPT image
  643. //containing all the partitions For UFS devices it could potentially be
  644. //invoked multiple times, once for each LUN containing critical image(s) and
  645. //their backups
  646. int prepare_partitions(enum boot_update_stage stage, const char *dev_path)
  647. {
  648. int r = 0;
  649. int fd = -1;
  650. int is_ufs = gpt_utils_is_ufs_device();
  651. enum gpt_state gpt_prim, gpt_second;
  652. enum boot_update_stage internal_stage;
  653. struct stat xbl_partition_stat;
  654. struct stat ufs_dir_stat;
  655. if (!dev_path) {
  656. fprintf(stderr, "%s: Invalid dev_path\n",
  657. __func__);
  658. r = -1;
  659. goto EXIT;
  660. }
  661. fd = open(dev_path, O_RDWR);
  662. if (fd < 0) {
  663. fprintf(stderr, "%s: Opening '%s' failed: %s\n",
  664. __func__,
  665. BLK_DEV_FILE,
  666. strerror(errno));
  667. r = -1;
  668. goto EXIT;
  669. }
  670. r = gpt_get_state(fd, PRIMARY_GPT, &gpt_prim) ||
  671. gpt_get_state(fd, SECONDARY_GPT, &gpt_second);
  672. if (r) {
  673. fprintf(stderr, "%s: Getting GPT headers state failed\n",
  674. __func__);
  675. goto EXIT;
  676. }
  677. /* These 2 combinations are unexpected and unacceptable */
  678. if (gpt_prim == GPT_BAD_CRC || gpt_second == GPT_BAD_CRC) {
  679. fprintf(stderr, "%s: GPT headers CRC corruption detected, aborting\n",
  680. __func__);
  681. r = -1;
  682. goto EXIT;
  683. }
  684. if (gpt_prim == GPT_BAD_SIGNATURE && gpt_second == GPT_BAD_SIGNATURE) {
  685. fprintf(stderr, "%s: Both GPT headers corrupted, aborting\n",
  686. __func__);
  687. r = -1;
  688. goto EXIT;
  689. }
  690. /* Check internal update stage according GPT headers' state */
  691. if (gpt_prim == GPT_OK && gpt_second == GPT_OK)
  692. internal_stage = UPDATE_MAIN;
  693. else if (gpt_prim == GPT_BAD_SIGNATURE)
  694. internal_stage = UPDATE_BACKUP;
  695. else if (gpt_second == GPT_BAD_SIGNATURE)
  696. internal_stage = UPDATE_FINALIZE;
  697. else {
  698. fprintf(stderr, "%s: Abnormal GPTs state: primary (%d), secondary (%d), "
  699. "aborting\n", __func__, gpt_prim, gpt_second);
  700. r = -1;
  701. goto EXIT;
  702. }
  703. /* Stage already set - ready for update, exitting */
  704. if ((int) stage == (int) internal_stage - 1)
  705. goto EXIT;
  706. /* Unexpected stage given */
  707. if (stage != internal_stage) {
  708. r = -1;
  709. goto EXIT;
  710. }
  711. switch (stage) {
  712. case UPDATE_MAIN:
  713. if (is_ufs) {
  714. if(stat(XBL_PRIMARY, &xbl_partition_stat)||
  715. stat(XBL_BACKUP, &xbl_partition_stat)){
  716. //Non fatal error. Just means this target does not
  717. //use XBL but relies on sbl whose update is handled
  718. //by the normal methods.
  719. fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
  720. __func__,
  721. strerror(errno));
  722. } else {
  723. //Switch the boot lun so that backup boot LUN is used
  724. r = gpt_utils_set_xbl_boot_partition(BACKUP_BOOT);
  725. if(r){
  726. fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
  727. __func__);
  728. goto EXIT;
  729. }
  730. }
  731. }
  732. //Fix up the backup GPT table so that it actually points to
  733. //the backup copy of the boot critical images
  734. fprintf(stderr, "%s: Preparing for primary partition update\n",
  735. __func__);
  736. r = gpt2_set_boot_chain(fd, BACKUP_BOOT);
  737. if (r) {
  738. if (r < 0)
  739. fprintf(stderr,
  740. "%s: Setting secondary GPT to backup boot failed\n",
  741. __func__);
  742. /* No backup partitions - do not corrupt GPT, do not flag error */
  743. else
  744. r = 0;
  745. goto EXIT;
  746. }
  747. //corrupt the primary GPT so that the backup(which now points to
  748. //the backup boot partitions is used)
  749. r = gpt_set_state(fd, PRIMARY_GPT, GPT_BAD_SIGNATURE);
  750. if (r) {
  751. fprintf(stderr, "%s: Corrupting primary GPT header failed\n",
  752. __func__);
  753. goto EXIT;
  754. }
  755. break;
  756. case UPDATE_BACKUP:
  757. if (is_ufs) {
  758. if(stat(XBL_PRIMARY, &xbl_partition_stat)||
  759. stat(XBL_BACKUP, &xbl_partition_stat)){
  760. //Non fatal error. Just means this target does not
  761. //use XBL but relies on sbl whose update is handled
  762. //by the normal methods.
  763. fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
  764. __func__,
  765. strerror(errno));
  766. } else {
  767. //Switch the boot lun so that backup boot LUN is used
  768. r = gpt_utils_set_xbl_boot_partition(NORMAL_BOOT);
  769. if(r) {
  770. fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
  771. __func__);
  772. goto EXIT;
  773. }
  774. }
  775. }
  776. //Fix the primary GPT header so that is used
  777. fprintf(stderr, "%s: Preparing for backup partition update\n",
  778. __func__);
  779. r = gpt_set_state(fd, PRIMARY_GPT, GPT_OK);
  780. if (r) {
  781. fprintf(stderr, "%s: Fixing primary GPT header failed\n",
  782. __func__);
  783. goto EXIT;
  784. }
  785. //Corrupt the scondary GPT header
  786. r = gpt_set_state(fd, SECONDARY_GPT, GPT_BAD_SIGNATURE);
  787. if (r) {
  788. fprintf(stderr, "%s: Corrupting secondary GPT header failed\n",
  789. __func__);
  790. goto EXIT;
  791. }
  792. break;
  793. case UPDATE_FINALIZE:
  794. //Undo the changes we had made in the UPDATE_MAIN stage so that the
  795. //primary/backup GPT headers once again point to the same set of
  796. //partitions
  797. fprintf(stderr, "%s: Finalizing partitions\n",
  798. __func__);
  799. r = gpt2_set_boot_chain(fd, NORMAL_BOOT);
  800. if (r < 0) {
  801. fprintf(stderr, "%s: Setting secondary GPT to normal boot failed\n",
  802. __func__);
  803. goto EXIT;
  804. }
  805. r = gpt_set_state(fd, SECONDARY_GPT, GPT_OK);
  806. if (r) {
  807. fprintf(stderr, "%s: Fixing secondary GPT header failed\n",
  808. __func__);
  809. goto EXIT;
  810. }
  811. break;
  812. default:;
  813. }
  814. EXIT:
  815. if (fd >= 0) {
  816. fsync(fd);
  817. close(fd);
  818. }
  819. return r;
  820. }
  821. int add_lun_to_update_list(char *lun_path, struct update_data *dat)
  822. {
  823. uint32_t i = 0;
  824. struct stat st;
  825. if (!lun_path || !dat){
  826. fprintf(stderr, "%s: Invalid data",
  827. __func__);
  828. return -1;
  829. }
  830. if (stat(lun_path, &st)) {
  831. fprintf(stderr, "%s: Unable to access %s. Skipping adding to list",
  832. __func__,
  833. lun_path);
  834. return -1;
  835. }
  836. if (dat->num_valid_entries == 0) {
  837. fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
  838. __func__,
  839. lun_path,
  840. i);
  841. strlcpy(dat->lun_list[0], lun_path,
  842. PATH_MAX * sizeof(char));
  843. dat->num_valid_entries = 1;
  844. } else {
  845. for (i = 0; (i < dat->num_valid_entries) &&
  846. (dat->num_valid_entries < MAX_LUNS - 1); i++) {
  847. //Check if the current LUN is not already part
  848. //of the lun list
  849. if (!strncmp(lun_path,dat->lun_list[i],
  850. strlen(dat->lun_list[i]))) {
  851. //LUN already in list..Return
  852. return 0;
  853. }
  854. }
  855. fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
  856. __func__,
  857. lun_path,
  858. dat->num_valid_entries);
  859. //Add LUN path lun list
  860. strlcpy(dat->lun_list[dat->num_valid_entries], lun_path,
  861. PATH_MAX * sizeof(char));
  862. dat->num_valid_entries++;
  863. }
  864. return 0;
  865. }
  866. int prepare_boot_update(enum boot_update_stage stage)
  867. {
  868. int r, fd;
  869. int is_ufs = gpt_utils_is_ufs_device();
  870. struct stat ufs_dir_stat;
  871. struct update_data data;
  872. int rcode = 0;
  873. uint32_t i = 0;
  874. int is_error = 0;
  875. const char ptn_swap_list[][MAX_GPT_NAME_SIZE] = { PTN_SWAP_LIST };
  876. //Holds /dev/block/bootdevice/by-name/*bak entry
  877. char buf[PATH_MAX] = {0};
  878. //Holds the resolved path of the symlink stored in buf
  879. char real_path[PATH_MAX] = {0};
  880. if (!is_ufs) {
  881. //emmc device. Just pass in path to mmcblk0
  882. return prepare_partitions(stage, BLK_DEV_FILE);
  883. } else {
  884. //Now we need to find the list of LUNs over
  885. //which the boot critical images are spread
  886. //and set them up for failsafe updates.To do
  887. //this we find out where the symlinks for the
  888. //each of the paths under
  889. ///dev/block/bootdevice/by-name/PTN_SWAP_LIST
  890. //actually point to.
  891. fprintf(stderr, "%s: Running on a UFS device\n",
  892. __func__);
  893. memset(&data, '\0', sizeof(struct update_data));
  894. for (i=0; i < ARRAY_SIZE(ptn_swap_list); i++) {
  895. //XBL on UFS does not follow the convention
  896. //of being loaded based on well known GUID'S.
  897. //We take care of switching the UFS boot LUN
  898. //explicitly later on.
  899. if (!strncmp(ptn_swap_list[i],PTN_XBL,strlen(PTN_XBL))
  900. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGOEM,strlen(PTN_MULTIIMGOEM))
  901. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGQTI,strlen(PTN_MULTIIMGQTI)))
  902. continue;
  903. snprintf(buf, sizeof(buf),
  904. "%s/%sbak",
  905. BOOT_DEV_DIR,
  906. ptn_swap_list[i]);
  907. if (stat(buf, &ufs_dir_stat)) {
  908. continue;
  909. }
  910. if (readlink(buf, real_path, sizeof(real_path) - 1) < 0)
  911. {
  912. fprintf(stderr, "%s: readlink error. Skipping %s",
  913. __func__,
  914. strerror(errno));
  915. } else {
  916. if(strlen(real_path) < PATH_TRUNCATE_LOC + 1){
  917. fprintf(stderr, "Unknown path.Skipping :%s:\n",
  918. real_path);
  919. } else {
  920. real_path[PATH_TRUNCATE_LOC] = '\0';
  921. add_lun_to_update_list(real_path, &data);
  922. }
  923. }
  924. memset(buf, '\0', sizeof(buf));
  925. memset(real_path, '\0', sizeof(real_path));
  926. }
  927. for (i=0; i < data.num_valid_entries; i++) {
  928. fprintf(stderr, "%s: Preparing %s for update stage %d\n",
  929. __func__,
  930. data.lun_list[i],
  931. stage);
  932. rcode = prepare_partitions(stage, data.lun_list[i]);
  933. if (rcode != 0)
  934. {
  935. fprintf(stderr, "%s: Failed to prepare %s.Continuing..\n",
  936. __func__,
  937. data.lun_list[i]);
  938. is_error = 1;
  939. }
  940. }
  941. }
  942. if (is_error)
  943. return -1;
  944. return 0;
  945. }
  946. //Given a parttion name(eg: rpm) get the path to the block device that
  947. //represents the GPT disk the partition resides on. In the case of emmc it
  948. //would be the default emmc dev(/dev/block/mmcblk0). In the case of UFS we look
  949. //through the /dev/block/bootdevice/by-name/ tree for partname, and resolve
  950. //the path to the LUN from there.
  951. static int get_dev_path_from_partition_name(const char *partname,
  952. char *buf,
  953. size_t buflen)
  954. {
  955. struct stat st;
  956. char path[PATH_MAX] = {0};
  957. if (!partname || !buf || buflen < ((PATH_TRUNCATE_LOC) + 1)) {
  958. ALOGE("%s: Invalid argument", __func__);
  959. goto error;
  960. }
  961. if (gpt_utils_is_ufs_device()) {
  962. //Need to find the lun that holds partition partname
  963. snprintf(path, sizeof(path),
  964. "%s/%s",
  965. BOOT_DEV_DIR,
  966. partname);
  967. if (stat(path, &st)) {
  968. goto error;
  969. }
  970. if (readlink(path, buf, buflen) < 0)
  971. {
  972. goto error;
  973. } else {
  974. buf[PATH_TRUNCATE_LOC] = '\0';
  975. }
  976. } else {
  977. snprintf(buf, buflen, BLK_DEV_FILE);
  978. }
  979. return 0;
  980. error:
  981. return -1;
  982. }
  983. int gpt_utils_get_partition_map(vector<string>& ptn_list,
  984. map<string, vector<string>>& partition_map) {
  985. char devpath[PATH_MAX] = {'\0'};
  986. map<string, vector<string>>::iterator it;
  987. if (ptn_list.size() < 1) {
  988. fprintf(stderr, "%s: Invalid ptn list\n", __func__);
  989. goto error;
  990. }
  991. //Go through the passed in list
  992. for (uint32_t i = 0; i < ptn_list.size(); i++)
  993. {
  994. //Key in the map is the path to the device that holds the
  995. //partition
  996. if (get_dev_path_from_partition_name(ptn_list[i].c_str(),
  997. devpath,
  998. sizeof(devpath))) {
  999. //Not necessarily an error. The partition may just
  1000. //not be present.
  1001. continue;
  1002. }
  1003. string path = devpath;
  1004. it = partition_map.find(path);
  1005. if (it != partition_map.end()) {
  1006. it->second.push_back(ptn_list[i]);
  1007. } else {
  1008. vector<string> str_vec;
  1009. str_vec.push_back( ptn_list[i]);
  1010. partition_map.insert(pair<string, vector<string>>
  1011. (path, str_vec));
  1012. }
  1013. memset(devpath, '\0', sizeof(devpath));
  1014. }
  1015. return 0;
  1016. error:
  1017. return -1;
  1018. }
  1019. //Get the block size of the disk represented by decsriptor fd
  1020. static uint32_t gpt_get_block_size(int fd)
  1021. {
  1022. uint32_t block_size = 0;
  1023. if (fd < 0) {
  1024. ALOGE("%s: invalid descriptor",
  1025. __func__);
  1026. goto error;
  1027. }
  1028. if (ioctl(fd, BLKSSZGET, &block_size) != 0) {
  1029. ALOGE("%s: Failed to get GPT dev block size : %s",
  1030. __func__,
  1031. strerror(errno));
  1032. goto error;
  1033. }
  1034. return block_size;
  1035. error:
  1036. return 0;
  1037. }
  1038. //Write the GPT header present in the passed in buffer back to the
  1039. //disk represented by fd
  1040. static int gpt_set_header(uint8_t *gpt_header, int fd,
  1041. enum gpt_instance instance)
  1042. {
  1043. uint32_t block_size = 0;
  1044. off64_t gpt_header_offset = 0;
  1045. if (!gpt_header || fd < 0) {
  1046. ALOGE("%s: Invalid arguments",
  1047. __func__);
  1048. goto error;
  1049. }
  1050. block_size = gpt_get_block_size(fd);
  1051. if (block_size == 0) {
  1052. ALOGE("%s: Failed to get block size", __func__);
  1053. goto error;
  1054. }
  1055. if (instance == PRIMARY_GPT)
  1056. gpt_header_offset = block_size;
  1057. else
  1058. gpt_header_offset = lseek64(fd, 0, SEEK_END) - block_size;
  1059. if (gpt_header_offset <= 0) {
  1060. ALOGE("%s: Failed to get gpt header offset",__func__);
  1061. goto error;
  1062. }
  1063. if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) {
  1064. ALOGE("%s: Failed to write back GPT header", __func__);
  1065. goto error;
  1066. }
  1067. return 0;
  1068. error:
  1069. return -1;
  1070. }
  1071. //Read out the GPT header for the disk that contains the partition partname
  1072. static uint8_t* gpt_get_header(const char *partname, enum gpt_instance instance)
  1073. {
  1074. uint8_t* hdr = NULL;
  1075. char devpath[PATH_MAX] = {0};
  1076. int64_t hdr_offset = 0;
  1077. uint32_t block_size = 0;
  1078. int fd = -1;
  1079. if (!partname) {
  1080. ALOGE("%s: Invalid partition name", __func__);
  1081. goto error;
  1082. }
  1083. if (get_dev_path_from_partition_name(partname, devpath, sizeof(devpath))
  1084. != 0) {
  1085. ALOGE("%s: Failed to resolve path for %s",
  1086. __func__,
  1087. partname);
  1088. goto error;
  1089. }
  1090. fd = open(devpath, O_RDWR);
  1091. if (fd < 0) {
  1092. ALOGE("%s: Failed to open %s : %s",
  1093. __func__,
  1094. devpath,
  1095. strerror(errno));
  1096. goto error;
  1097. }
  1098. block_size = gpt_get_block_size(fd);
  1099. if (block_size == 0)
  1100. {
  1101. ALOGE("%s: Failed to get gpt block size for %s",
  1102. __func__,
  1103. partname);
  1104. goto error;
  1105. }
  1106. hdr = (uint8_t*)malloc(block_size);
  1107. if (!hdr) {
  1108. ALOGE("%s: Failed to allocate memory for gpt header",
  1109. __func__);
  1110. }
  1111. if (instance == PRIMARY_GPT)
  1112. hdr_offset = block_size;
  1113. else {
  1114. hdr_offset = lseek64(fd, 0, SEEK_END) - block_size;
  1115. }
  1116. if (hdr_offset < 0) {
  1117. ALOGE("%s: Failed to get gpt header offset",
  1118. __func__);
  1119. goto error;
  1120. }
  1121. if (blk_rw(fd, 0, hdr_offset, hdr, block_size)) {
  1122. ALOGE("%s: Failed to read GPT header from device",
  1123. __func__);
  1124. goto error;
  1125. }
  1126. close(fd);
  1127. return hdr;
  1128. error:
  1129. if (fd >= 0)
  1130. close(fd);
  1131. if (hdr)
  1132. free(hdr);
  1133. return NULL;
  1134. }
  1135. //Returns the partition entry array based on the
  1136. //passed in buffer which contains the gpt header.
  1137. //The fd here is the descriptor for the 'disk' which
  1138. //holds the partition
  1139. static uint8_t* gpt_get_pentry_arr(uint8_t *hdr, int fd)
  1140. {
  1141. uint64_t pentries_start = 0;
  1142. uint32_t pentry_size = 0;
  1143. uint32_t block_size = 0;
  1144. uint32_t pentries_arr_size = 0;
  1145. uint8_t *pentry_arr = NULL;
  1146. int rc = 0;
  1147. if (!hdr) {
  1148. ALOGE("%s: Invalid header", __func__);
  1149. goto error;
  1150. }
  1151. if (fd < 0) {
  1152. ALOGE("%s: Invalid fd", __func__);
  1153. goto error;
  1154. }
  1155. block_size = gpt_get_block_size(fd);
  1156. if (!block_size) {
  1157. ALOGE("%s: Failed to get gpt block size for",
  1158. __func__);
  1159. goto error;
  1160. }
  1161. pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
  1162. pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
  1163. pentries_arr_size =
  1164. GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
  1165. pentry_arr = (uint8_t*)calloc(1, pentries_arr_size);
  1166. if (!pentry_arr) {
  1167. ALOGE("%s: Failed to allocate memory for partition array",
  1168. __func__);
  1169. goto error;
  1170. }
  1171. rc = blk_rw(fd, 0,
  1172. pentries_start,
  1173. pentry_arr,
  1174. pentries_arr_size);
  1175. if (rc) {
  1176. ALOGE("%s: Failed to read partition entry array",
  1177. __func__);
  1178. goto error;
  1179. }
  1180. return pentry_arr;
  1181. error:
  1182. if (pentry_arr)
  1183. free(pentry_arr);
  1184. return NULL;
  1185. }
  1186. static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t* arr)
  1187. {
  1188. uint32_t block_size = 0;
  1189. uint64_t pentries_start = 0;
  1190. uint32_t pentry_size = 0;
  1191. uint32_t pentries_arr_size = 0;
  1192. int rc = 0;
  1193. if (!hdr || fd < 0 || !arr) {
  1194. ALOGE("%s: Invalid argument", __func__);
  1195. goto error;
  1196. }
  1197. block_size = gpt_get_block_size(fd);
  1198. if (!block_size) {
  1199. ALOGE("%s: Failed to get gpt block size for",
  1200. __func__);
  1201. goto error;
  1202. }
  1203. pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
  1204. pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
  1205. pentries_arr_size =
  1206. GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
  1207. rc = blk_rw(fd, 1,
  1208. pentries_start,
  1209. arr,
  1210. pentries_arr_size);
  1211. if (rc) {
  1212. ALOGE("%s: Failed to read partition entry array",
  1213. __func__);
  1214. goto error;
  1215. }
  1216. return 0;
  1217. error:
  1218. return -1;
  1219. }
  1220. //Allocate a handle used by calls to the "gpt_disk" api's
  1221. struct gpt_disk * gpt_disk_alloc()
  1222. {
  1223. struct gpt_disk *disk;
  1224. disk = (struct gpt_disk *)malloc(sizeof(struct gpt_disk));
  1225. if (!disk) {
  1226. ALOGE("%s: Failed to allocate memory", __func__);
  1227. goto end;
  1228. }
  1229. memset(disk, 0, sizeof(struct gpt_disk));
  1230. end:
  1231. return disk;
  1232. }
  1233. //Free previously allocated/initialized handle
  1234. void gpt_disk_free(struct gpt_disk *disk)
  1235. {
  1236. if (!disk)
  1237. return;
  1238. if (disk->hdr)
  1239. free(disk->hdr);
  1240. if (disk->hdr_bak)
  1241. free(disk->hdr_bak);
  1242. if (disk->pentry_arr)
  1243. free(disk->pentry_arr);
  1244. if (disk->pentry_arr_bak)
  1245. free(disk->pentry_arr_bak);
  1246. free(disk);
  1247. return;
  1248. }
  1249. //fills up the passed in gpt_disk struct with information about the
  1250. //disk represented by path dev. Returns 0 on success and -1 on error.
  1251. int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *dsk)
  1252. {
  1253. struct gpt_disk *disk = NULL;
  1254. int fd = -1;
  1255. uint32_t gpt_header_size = 0;
  1256. uint32_t crc_zero;
  1257. crc_zero = crc32(0L, Z_NULL, 0);
  1258. if (!dsk || !dev) {
  1259. ALOGE("%s: Invalid arguments", __func__);
  1260. goto error;
  1261. }
  1262. disk = dsk;
  1263. disk->hdr = gpt_get_header(dev, PRIMARY_GPT);
  1264. if (!disk->hdr) {
  1265. ALOGE("%s: Failed to get primary header", __func__);
  1266. goto error;
  1267. }
  1268. gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
  1269. disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
  1270. disk->hdr_bak = gpt_get_header(dev, SECONDARY_GPT);
  1271. if (!disk->hdr_bak) {
  1272. ALOGE("%s: Failed to get backup header", __func__);
  1273. goto error;
  1274. }
  1275. disk->hdr_bak_crc = crc32(crc_zero, disk->hdr_bak, gpt_header_size);
  1276. //Descriptor for the block device. We will use this for further
  1277. //modifications to the partition table
  1278. if (get_dev_path_from_partition_name(dev,
  1279. disk->devpath,
  1280. sizeof(disk->devpath)) != 0) {
  1281. ALOGE("%s: Failed to resolve path for %s",
  1282. __func__,
  1283. dev);
  1284. goto error;
  1285. }
  1286. fd = open(disk->devpath, O_RDWR);
  1287. if (fd < 0) {
  1288. ALOGE("%s: Failed to open %s: %s",
  1289. __func__,
  1290. disk->devpath,
  1291. strerror(errno));
  1292. goto error;
  1293. }
  1294. disk->pentry_arr = gpt_get_pentry_arr(disk->hdr, fd);
  1295. if (!disk->pentry_arr) {
  1296. ALOGE("%s: Failed to obtain partition entry array",
  1297. __func__);
  1298. goto error;
  1299. }
  1300. disk->pentry_arr_bak = gpt_get_pentry_arr(disk->hdr_bak, fd);
  1301. if (!disk->pentry_arr_bak) {
  1302. ALOGE("%s: Failed to obtain backup partition entry array",
  1303. __func__);
  1304. goto error;
  1305. }
  1306. disk->pentry_size = GET_4_BYTES(disk->hdr + PENTRY_SIZE_OFFSET);
  1307. disk->pentry_arr_size =
  1308. GET_4_BYTES(disk->hdr + PARTITION_COUNT_OFFSET) *
  1309. disk->pentry_size;
  1310. disk->pentry_arr_crc = GET_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET);
  1311. disk->pentry_arr_bak_crc = GET_4_BYTES(disk->hdr_bak +
  1312. PARTITION_CRC_OFFSET);
  1313. disk->block_size = gpt_get_block_size(fd);
  1314. close(fd);
  1315. disk->is_initialized = GPT_DISK_INIT_MAGIC;
  1316. return 0;
  1317. error:
  1318. if (fd >= 0)
  1319. close(fd);
  1320. return -1;
  1321. }
  1322. //Get pointer to partition entry from a allocated gpt_disk structure
  1323. uint8_t* gpt_disk_get_pentry(struct gpt_disk *disk,
  1324. const char *partname,
  1325. enum gpt_instance instance)
  1326. {
  1327. uint8_t *ptn_arr = NULL;
  1328. if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) {
  1329. ALOGE("%s: Invalid argument",__func__);
  1330. goto error;
  1331. }
  1332. ptn_arr = (instance == PRIMARY_GPT) ?
  1333. disk->pentry_arr : disk->pentry_arr_bak;
  1334. return (gpt_pentry_seek(partname, ptn_arr,
  1335. ptn_arr + disk->pentry_arr_size ,
  1336. disk->pentry_size));
  1337. error:
  1338. return NULL;
  1339. }
  1340. //Update CRC values for the various components of the gpt_disk
  1341. //structure. This function should be called after any of the fields
  1342. //have been updated before the structure contents are written back to
  1343. //disk.
  1344. int gpt_disk_update_crc(struct gpt_disk *disk)
  1345. {
  1346. uint32_t gpt_header_size = 0;
  1347. uint32_t crc_zero;
  1348. crc_zero = crc32(0L, Z_NULL, 0);
  1349. if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
  1350. ALOGE("%s: invalid argument", __func__);
  1351. goto error;
  1352. }
  1353. //Recalculate the CRC of the primary partiton array
  1354. disk->pentry_arr_crc = crc32(crc_zero,
  1355. disk->pentry_arr,
  1356. disk->pentry_arr_size);
  1357. //Recalculate the CRC of the backup partition array
  1358. disk->pentry_arr_bak_crc = crc32(crc_zero,
  1359. disk->pentry_arr_bak,
  1360. disk->pentry_arr_size);
  1361. //Update the partition CRC value in the primary GPT header
  1362. PUT_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET, disk->pentry_arr_crc);
  1363. //Update the partition CRC value in the backup GPT header
  1364. PUT_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET,
  1365. disk->pentry_arr_bak_crc);
  1366. //Update the CRC value of the primary header
  1367. gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
  1368. //Header CRC is calculated with its own CRC field set to 0
  1369. PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, 0);
  1370. PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, 0);
  1371. disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
  1372. disk->hdr_bak_crc = crc32(crc_zero, disk->hdr_bak, gpt_header_size);
  1373. PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, disk->hdr_crc);
  1374. PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, disk->hdr_bak_crc);
  1375. return 0;
  1376. error:
  1377. return -1;
  1378. }
  1379. //Write the contents of struct gpt_disk back to the actual disk
  1380. int gpt_disk_commit(struct gpt_disk *disk)
  1381. {
  1382. int fd = -1;
  1383. if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)){
  1384. ALOGE("%s: Invalid args", __func__);
  1385. goto error;
  1386. }
  1387. fd = open(disk->devpath, O_RDWR | O_DSYNC);
  1388. if (fd < 0) {
  1389. ALOGE("%s: Failed to open %s: %s",
  1390. __func__,
  1391. disk->devpath,
  1392. strerror(errno));
  1393. goto error;
  1394. }
  1395. //Write the primary header
  1396. if(gpt_set_header(disk->hdr, fd, PRIMARY_GPT) != 0) {
  1397. ALOGE("%s: Failed to update primary GPT header",
  1398. __func__);
  1399. goto error;
  1400. }
  1401. //Write back the primary partition array
  1402. if (gpt_set_pentry_arr(disk->hdr, fd, disk->pentry_arr)) {
  1403. ALOGE("%s: Failed to write primary GPT partition arr",
  1404. __func__);
  1405. goto error;
  1406. }
  1407. //Write back the secondary header
  1408. if(gpt_set_header(disk->hdr_bak, fd, SECONDARY_GPT) != 0) {
  1409. ALOGE("%s: Failed to update secondary GPT header",
  1410. __func__);
  1411. goto error;
  1412. }
  1413. //Write back the secondary partition array
  1414. if (gpt_set_pentry_arr(disk->hdr_bak, fd, disk->pentry_arr_bak)) {
  1415. ALOGE("%s: Failed to write secondary GPT partition arr",
  1416. __func__);
  1417. goto error;
  1418. }
  1419. fsync(fd);
  1420. close(fd);
  1421. return 0;
  1422. error:
  1423. if (fd >= 0)
  1424. close(fd);
  1425. return -1;
  1426. }