gpt-utils.cpp 55 KB

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