gpt-utils.cpp 55 KB

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