gpt-utils.cpp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520
  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. if (!dev_path) {
  653. fprintf(stderr, "%s: Invalid dev_path\n",
  654. __func__);
  655. r = -1;
  656. goto EXIT;
  657. }
  658. fd = open(dev_path, O_RDWR);
  659. if (fd < 0) {
  660. fprintf(stderr, "%s: Opening '%s' failed: %s\n",
  661. __func__,
  662. BLK_DEV_FILE,
  663. strerror(errno));
  664. r = -1;
  665. goto EXIT;
  666. }
  667. r = gpt_get_state(fd, PRIMARY_GPT, &gpt_prim) ||
  668. gpt_get_state(fd, SECONDARY_GPT, &gpt_second);
  669. if (r) {
  670. fprintf(stderr, "%s: Getting GPT headers state failed\n",
  671. __func__);
  672. goto EXIT;
  673. }
  674. /* These 2 combinations are unexpected and unacceptable */
  675. if (gpt_prim == GPT_BAD_CRC || gpt_second == GPT_BAD_CRC) {
  676. fprintf(stderr, "%s: GPT headers CRC corruption detected, aborting\n",
  677. __func__);
  678. r = -1;
  679. goto EXIT;
  680. }
  681. if (gpt_prim == GPT_BAD_SIGNATURE && gpt_second == GPT_BAD_SIGNATURE) {
  682. fprintf(stderr, "%s: Both GPT headers corrupted, aborting\n",
  683. __func__);
  684. r = -1;
  685. goto EXIT;
  686. }
  687. /* Check internal update stage according GPT headers' state */
  688. if (gpt_prim == GPT_OK && gpt_second == GPT_OK)
  689. internal_stage = UPDATE_MAIN;
  690. else if (gpt_prim == GPT_BAD_SIGNATURE)
  691. internal_stage = UPDATE_BACKUP;
  692. else if (gpt_second == GPT_BAD_SIGNATURE)
  693. internal_stage = UPDATE_FINALIZE;
  694. else {
  695. fprintf(stderr, "%s: Abnormal GPTs state: primary (%d), secondary (%d), "
  696. "aborting\n", __func__, gpt_prim, gpt_second);
  697. r = -1;
  698. goto EXIT;
  699. }
  700. /* Stage already set - ready for update, exitting */
  701. if ((int) stage == (int) internal_stage - 1)
  702. goto EXIT;
  703. /* Unexpected stage given */
  704. if (stage != internal_stage) {
  705. r = -1;
  706. goto EXIT;
  707. }
  708. switch (stage) {
  709. case UPDATE_MAIN:
  710. if (is_ufs) {
  711. if(stat(XBL_PRIMARY, &xbl_partition_stat)||
  712. stat(XBL_BACKUP, &xbl_partition_stat)){
  713. //Non fatal error. Just means this target does not
  714. //use XBL but relies on sbl whose update is handled
  715. //by the normal methods.
  716. fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
  717. __func__,
  718. strerror(errno));
  719. } else {
  720. //Switch the boot lun so that backup boot LUN is used
  721. r = gpt_utils_set_xbl_boot_partition(BACKUP_BOOT);
  722. if(r){
  723. fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
  724. __func__);
  725. goto EXIT;
  726. }
  727. }
  728. }
  729. //Fix up the backup GPT table so that it actually points to
  730. //the backup copy of the boot critical images
  731. fprintf(stderr, "%s: Preparing for primary partition update\n",
  732. __func__);
  733. r = gpt2_set_boot_chain(fd, BACKUP_BOOT);
  734. if (r) {
  735. if (r < 0)
  736. fprintf(stderr,
  737. "%s: Setting secondary GPT to backup boot failed\n",
  738. __func__);
  739. /* No backup partitions - do not corrupt GPT, do not flag error */
  740. else
  741. r = 0;
  742. goto EXIT;
  743. }
  744. //corrupt the primary GPT so that the backup(which now points to
  745. //the backup boot partitions is used)
  746. r = gpt_set_state(fd, PRIMARY_GPT, GPT_BAD_SIGNATURE);
  747. if (r) {
  748. fprintf(stderr, "%s: Corrupting primary GPT header failed\n",
  749. __func__);
  750. goto EXIT;
  751. }
  752. break;
  753. case UPDATE_BACKUP:
  754. if (is_ufs) {
  755. if(stat(XBL_PRIMARY, &xbl_partition_stat)||
  756. stat(XBL_BACKUP, &xbl_partition_stat)){
  757. //Non fatal error. Just means this target does not
  758. //use XBL but relies on sbl whose update is handled
  759. //by the normal methods.
  760. fprintf(stderr, "%s: xbl part not found(%s).Assuming sbl in use\n",
  761. __func__,
  762. strerror(errno));
  763. } else {
  764. //Switch the boot lun so that backup boot LUN is used
  765. r = gpt_utils_set_xbl_boot_partition(NORMAL_BOOT);
  766. if(r) {
  767. fprintf(stderr, "%s: Failed to set xbl backup partition as boot\n",
  768. __func__);
  769. goto EXIT;
  770. }
  771. }
  772. }
  773. //Fix the primary GPT header so that is used
  774. fprintf(stderr, "%s: Preparing for backup partition update\n",
  775. __func__);
  776. r = gpt_set_state(fd, PRIMARY_GPT, GPT_OK);
  777. if (r) {
  778. fprintf(stderr, "%s: Fixing primary GPT header failed\n",
  779. __func__);
  780. goto EXIT;
  781. }
  782. //Corrupt the scondary GPT header
  783. r = gpt_set_state(fd, SECONDARY_GPT, GPT_BAD_SIGNATURE);
  784. if (r) {
  785. fprintf(stderr, "%s: Corrupting secondary GPT header failed\n",
  786. __func__);
  787. goto EXIT;
  788. }
  789. break;
  790. case UPDATE_FINALIZE:
  791. //Undo the changes we had made in the UPDATE_MAIN stage so that the
  792. //primary/backup GPT headers once again point to the same set of
  793. //partitions
  794. fprintf(stderr, "%s: Finalizing partitions\n",
  795. __func__);
  796. r = gpt2_set_boot_chain(fd, NORMAL_BOOT);
  797. if (r < 0) {
  798. fprintf(stderr, "%s: Setting secondary GPT to normal boot failed\n",
  799. __func__);
  800. goto EXIT;
  801. }
  802. r = gpt_set_state(fd, SECONDARY_GPT, GPT_OK);
  803. if (r) {
  804. fprintf(stderr, "%s: Fixing secondary GPT header failed\n",
  805. __func__);
  806. goto EXIT;
  807. }
  808. break;
  809. default:;
  810. }
  811. EXIT:
  812. if (fd >= 0) {
  813. fsync(fd);
  814. close(fd);
  815. }
  816. return r;
  817. }
  818. int add_lun_to_update_list(char *lun_path, struct update_data *dat)
  819. {
  820. uint32_t i = 0;
  821. struct stat st;
  822. if (!lun_path || !dat){
  823. fprintf(stderr, "%s: Invalid data",
  824. __func__);
  825. return -1;
  826. }
  827. if (stat(lun_path, &st)) {
  828. fprintf(stderr, "%s: Unable to access %s. Skipping adding to list",
  829. __func__,
  830. lun_path);
  831. return -1;
  832. }
  833. if (dat->num_valid_entries == 0) {
  834. fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
  835. __func__,
  836. lun_path,
  837. i);
  838. strlcpy(dat->lun_list[0], lun_path,
  839. PATH_MAX * sizeof(char));
  840. dat->num_valid_entries = 1;
  841. } else {
  842. for (i = 0; (i < dat->num_valid_entries) &&
  843. (dat->num_valid_entries < MAX_LUNS - 1); i++) {
  844. //Check if the current LUN is not already part
  845. //of the lun list
  846. if (!strncmp(lun_path,dat->lun_list[i],
  847. strlen(dat->lun_list[i]))) {
  848. //LUN already in list..Return
  849. return 0;
  850. }
  851. }
  852. fprintf(stderr, "%s: Copying %s into lun_list[%d]\n",
  853. __func__,
  854. lun_path,
  855. dat->num_valid_entries);
  856. //Add LUN path lun list
  857. strlcpy(dat->lun_list[dat->num_valid_entries], lun_path,
  858. PATH_MAX * sizeof(char));
  859. dat->num_valid_entries++;
  860. }
  861. return 0;
  862. }
  863. int prepare_boot_update(enum boot_update_stage stage)
  864. {
  865. int is_ufs = gpt_utils_is_ufs_device();
  866. struct stat ufs_dir_stat;
  867. struct update_data data;
  868. int rcode = 0;
  869. uint32_t i = 0;
  870. int is_error = 0;
  871. const char ptn_swap_list[][MAX_GPT_NAME_SIZE] = { PTN_SWAP_LIST };
  872. //Holds /dev/block/bootdevice/by-name/*bak entry
  873. char buf[PATH_MAX] = {0};
  874. //Holds the resolved path of the symlink stored in buf
  875. char real_path[PATH_MAX] = {0};
  876. if (!is_ufs) {
  877. //emmc device. Just pass in path to mmcblk0
  878. return prepare_partitions(stage, BLK_DEV_FILE);
  879. } else {
  880. //Now we need to find the list of LUNs over
  881. //which the boot critical images are spread
  882. //and set them up for failsafe updates.To do
  883. //this we find out where the symlinks for the
  884. //each of the paths under
  885. ///dev/block/bootdevice/by-name/PTN_SWAP_LIST
  886. //actually point to.
  887. fprintf(stderr, "%s: Running on a UFS device\n",
  888. __func__);
  889. memset(&data, '\0', sizeof(struct update_data));
  890. for (i=0; i < ARRAY_SIZE(ptn_swap_list); i++) {
  891. //XBL on UFS does not follow the convention
  892. //of being loaded based on well known GUID'S.
  893. //We take care of switching the UFS boot LUN
  894. //explicitly later on.
  895. if (!strncmp(ptn_swap_list[i],PTN_XBL,strlen(PTN_XBL))
  896. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGOEM,strlen(PTN_MULTIIMGOEM))
  897. || !strncmp(ptn_swap_list[i],PTN_MULTIIMGQTI,strlen(PTN_MULTIIMGQTI)))
  898. continue;
  899. snprintf(buf, sizeof(buf),
  900. "%s/%sbak",
  901. BOOT_DEV_DIR,
  902. ptn_swap_list[i]);
  903. if (stat(buf, &ufs_dir_stat)) {
  904. continue;
  905. }
  906. if (readlink(buf, real_path, sizeof(real_path) - 1) < 0)
  907. {
  908. fprintf(stderr, "%s: readlink error. Skipping %s",
  909. __func__,
  910. strerror(errno));
  911. } else {
  912. if(strlen(real_path) < PATH_TRUNCATE_LOC + 1){
  913. fprintf(stderr, "Unknown path.Skipping :%s:\n",
  914. real_path);
  915. } else {
  916. real_path[PATH_TRUNCATE_LOC] = '\0';
  917. add_lun_to_update_list(real_path, &data);
  918. }
  919. }
  920. memset(buf, '\0', sizeof(buf));
  921. memset(real_path, '\0', sizeof(real_path));
  922. }
  923. for (i=0; i < data.num_valid_entries; i++) {
  924. fprintf(stderr, "%s: Preparing %s for update stage %d\n",
  925. __func__,
  926. data.lun_list[i],
  927. stage);
  928. rcode = prepare_partitions(stage, data.lun_list[i]);
  929. if (rcode != 0)
  930. {
  931. fprintf(stderr, "%s: Failed to prepare %s.Continuing..\n",
  932. __func__,
  933. data.lun_list[i]);
  934. is_error = 1;
  935. }
  936. }
  937. }
  938. if (is_error)
  939. return -1;
  940. return 0;
  941. }
  942. //Given a parttion name(eg: rpm) get the path to the block device that
  943. //represents the GPT disk the partition resides on. In the case of emmc it
  944. //would be the default emmc dev(/dev/block/mmcblk0). In the case of UFS we look
  945. //through the /dev/block/bootdevice/by-name/ tree for partname, and resolve
  946. //the path to the LUN from there.
  947. static int get_dev_path_from_partition_name(const char *partname,
  948. char *buf,
  949. size_t buflen)
  950. {
  951. struct stat st;
  952. char path[PATH_MAX] = {0};
  953. if (!partname || !buf || buflen < ((PATH_TRUNCATE_LOC) + 1)) {
  954. ALOGE("%s: Invalid argument", __func__);
  955. goto error;
  956. }
  957. if (gpt_utils_is_ufs_device()) {
  958. //Need to find the lun that holds partition partname
  959. snprintf(path, sizeof(path),
  960. "%s/%s",
  961. BOOT_DEV_DIR,
  962. partname);
  963. if (stat(path, &st)) {
  964. goto error;
  965. }
  966. if (readlink(path, buf, buflen) < 0)
  967. {
  968. goto error;
  969. } else {
  970. buf[PATH_TRUNCATE_LOC] = '\0';
  971. }
  972. } else {
  973. snprintf(buf, buflen, BLK_DEV_FILE);
  974. }
  975. return 0;
  976. error:
  977. return -1;
  978. }
  979. int gpt_utils_get_partition_map(vector<string>& ptn_list,
  980. map<string, vector<string>>& partition_map) {
  981. char devpath[PATH_MAX] = {'\0'};
  982. map<string, vector<string>>::iterator it;
  983. if (ptn_list.size() < 1) {
  984. fprintf(stderr, "%s: Invalid ptn list\n", __func__);
  985. goto error;
  986. }
  987. //Go through the passed in list
  988. for (uint32_t i = 0; i < ptn_list.size(); i++)
  989. {
  990. //Key in the map is the path to the device that holds the
  991. //partition
  992. if (get_dev_path_from_partition_name(ptn_list[i].c_str(),
  993. devpath,
  994. sizeof(devpath))) {
  995. //Not necessarily an error. The partition may just
  996. //not be present.
  997. continue;
  998. }
  999. string path = devpath;
  1000. it = partition_map.find(path);
  1001. if (it != partition_map.end()) {
  1002. it->second.push_back(ptn_list[i]);
  1003. } else {
  1004. vector<string> str_vec;
  1005. str_vec.push_back( ptn_list[i]);
  1006. partition_map.insert(pair<string, vector<string>>
  1007. (path, str_vec));
  1008. }
  1009. memset(devpath, '\0', sizeof(devpath));
  1010. }
  1011. return 0;
  1012. error:
  1013. return -1;
  1014. }
  1015. //Get the block size of the disk represented by decsriptor fd
  1016. static uint32_t gpt_get_block_size(int fd)
  1017. {
  1018. uint32_t block_size = 0;
  1019. if (fd < 0) {
  1020. ALOGE("%s: invalid descriptor",
  1021. __func__);
  1022. goto error;
  1023. }
  1024. if (ioctl(fd, BLKSSZGET, &block_size) != 0) {
  1025. ALOGE("%s: Failed to get GPT dev block size : %s",
  1026. __func__,
  1027. strerror(errno));
  1028. goto error;
  1029. }
  1030. return block_size;
  1031. error:
  1032. return 0;
  1033. }
  1034. //Write the GPT header present in the passed in buffer back to the
  1035. //disk represented by fd
  1036. static int gpt_set_header(uint8_t *gpt_header, int fd,
  1037. enum gpt_instance instance)
  1038. {
  1039. uint32_t block_size = 0;
  1040. off64_t gpt_header_offset = 0;
  1041. if (!gpt_header || fd < 0) {
  1042. ALOGE("%s: Invalid arguments",
  1043. __func__);
  1044. goto error;
  1045. }
  1046. block_size = gpt_get_block_size(fd);
  1047. if (block_size == 0) {
  1048. ALOGE("%s: Failed to get block size", __func__);
  1049. goto error;
  1050. }
  1051. if (instance == PRIMARY_GPT)
  1052. gpt_header_offset = block_size;
  1053. else
  1054. gpt_header_offset = lseek64(fd, 0, SEEK_END) - block_size;
  1055. if (gpt_header_offset <= 0) {
  1056. ALOGE("%s: Failed to get gpt header offset",__func__);
  1057. goto error;
  1058. }
  1059. if (blk_rw(fd, 1, gpt_header_offset, gpt_header, block_size)) {
  1060. ALOGE("%s: Failed to write back GPT header", __func__);
  1061. goto error;
  1062. }
  1063. return 0;
  1064. error:
  1065. return -1;
  1066. }
  1067. //Read out the GPT header for the disk that contains the partition partname
  1068. static uint8_t* gpt_get_header(const char *partname, enum gpt_instance instance)
  1069. {
  1070. uint8_t* hdr = NULL;
  1071. char devpath[PATH_MAX] = {0};
  1072. int64_t hdr_offset = 0;
  1073. uint32_t block_size = 0;
  1074. int fd = -1;
  1075. if (!partname) {
  1076. ALOGE("%s: Invalid partition name", __func__);
  1077. goto error;
  1078. }
  1079. if (get_dev_path_from_partition_name(partname, devpath, sizeof(devpath))
  1080. != 0) {
  1081. ALOGE("%s: Failed to resolve path for %s",
  1082. __func__,
  1083. partname);
  1084. goto error;
  1085. }
  1086. fd = open(devpath, O_RDWR);
  1087. if (fd < 0) {
  1088. ALOGE("%s: Failed to open %s : %s",
  1089. __func__,
  1090. devpath,
  1091. strerror(errno));
  1092. goto error;
  1093. }
  1094. block_size = gpt_get_block_size(fd);
  1095. if (block_size == 0)
  1096. {
  1097. ALOGE("%s: Failed to get gpt block size for %s",
  1098. __func__,
  1099. partname);
  1100. goto error;
  1101. }
  1102. hdr = (uint8_t*)malloc(block_size);
  1103. if (!hdr) {
  1104. ALOGE("%s: Failed to allocate memory for gpt header",
  1105. __func__);
  1106. }
  1107. if (instance == PRIMARY_GPT)
  1108. hdr_offset = block_size;
  1109. else {
  1110. hdr_offset = lseek64(fd, 0, SEEK_END) - block_size;
  1111. }
  1112. if (hdr_offset < 0) {
  1113. ALOGE("%s: Failed to get gpt header offset",
  1114. __func__);
  1115. goto error;
  1116. }
  1117. if (blk_rw(fd, 0, hdr_offset, hdr, block_size)) {
  1118. ALOGE("%s: Failed to read GPT header from device",
  1119. __func__);
  1120. goto error;
  1121. }
  1122. close(fd);
  1123. return hdr;
  1124. error:
  1125. if (fd >= 0)
  1126. close(fd);
  1127. if (hdr)
  1128. free(hdr);
  1129. return NULL;
  1130. }
  1131. //Returns the partition entry array based on the
  1132. //passed in buffer which contains the gpt header.
  1133. //The fd here is the descriptor for the 'disk' which
  1134. //holds the partition
  1135. static uint8_t* gpt_get_pentry_arr(uint8_t *hdr, int fd)
  1136. {
  1137. uint64_t pentries_start = 0;
  1138. uint32_t pentry_size = 0;
  1139. uint32_t block_size = 0;
  1140. uint32_t pentries_arr_size = 0;
  1141. uint8_t *pentry_arr = NULL;
  1142. int rc = 0;
  1143. if (!hdr) {
  1144. ALOGE("%s: Invalid header", __func__);
  1145. goto error;
  1146. }
  1147. if (fd < 0) {
  1148. ALOGE("%s: Invalid fd", __func__);
  1149. goto error;
  1150. }
  1151. block_size = gpt_get_block_size(fd);
  1152. if (!block_size) {
  1153. ALOGE("%s: Failed to get gpt block size for",
  1154. __func__);
  1155. goto error;
  1156. }
  1157. pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
  1158. pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
  1159. pentries_arr_size =
  1160. GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
  1161. pentry_arr = (uint8_t*)calloc(1, pentries_arr_size);
  1162. if (!pentry_arr) {
  1163. ALOGE("%s: Failed to allocate memory for partition array",
  1164. __func__);
  1165. goto error;
  1166. }
  1167. rc = blk_rw(fd, 0,
  1168. pentries_start,
  1169. pentry_arr,
  1170. pentries_arr_size);
  1171. if (rc) {
  1172. ALOGE("%s: Failed to read partition entry array",
  1173. __func__);
  1174. goto error;
  1175. }
  1176. return pentry_arr;
  1177. error:
  1178. if (pentry_arr)
  1179. free(pentry_arr);
  1180. return NULL;
  1181. }
  1182. static int gpt_set_pentry_arr(uint8_t *hdr, int fd, uint8_t* arr)
  1183. {
  1184. uint32_t block_size = 0;
  1185. uint64_t pentries_start = 0;
  1186. uint32_t pentry_size = 0;
  1187. uint32_t pentries_arr_size = 0;
  1188. int rc = 0;
  1189. if (!hdr || fd < 0 || !arr) {
  1190. ALOGE("%s: Invalid argument", __func__);
  1191. goto error;
  1192. }
  1193. block_size = gpt_get_block_size(fd);
  1194. if (!block_size) {
  1195. ALOGE("%s: Failed to get gpt block size for",
  1196. __func__);
  1197. goto error;
  1198. }
  1199. pentries_start = GET_8_BYTES(hdr + PENTRIES_OFFSET) * block_size;
  1200. pentry_size = GET_4_BYTES(hdr + PENTRY_SIZE_OFFSET);
  1201. pentries_arr_size =
  1202. GET_4_BYTES(hdr + PARTITION_COUNT_OFFSET) * pentry_size;
  1203. rc = blk_rw(fd, 1,
  1204. pentries_start,
  1205. arr,
  1206. pentries_arr_size);
  1207. if (rc) {
  1208. ALOGE("%s: Failed to read partition entry array",
  1209. __func__);
  1210. goto error;
  1211. }
  1212. return 0;
  1213. error:
  1214. return -1;
  1215. }
  1216. //Allocate a handle used by calls to the "gpt_disk" api's
  1217. struct gpt_disk * gpt_disk_alloc()
  1218. {
  1219. struct gpt_disk *disk;
  1220. disk = (struct gpt_disk *)malloc(sizeof(struct gpt_disk));
  1221. if (!disk) {
  1222. ALOGE("%s: Failed to allocate memory", __func__);
  1223. goto end;
  1224. }
  1225. memset(disk, 0, sizeof(struct gpt_disk));
  1226. end:
  1227. return disk;
  1228. }
  1229. //Free previously allocated/initialized handle
  1230. void gpt_disk_free(struct gpt_disk *disk)
  1231. {
  1232. if (!disk)
  1233. return;
  1234. if (disk->hdr)
  1235. free(disk->hdr);
  1236. if (disk->hdr_bak)
  1237. free(disk->hdr_bak);
  1238. if (disk->pentry_arr)
  1239. free(disk->pentry_arr);
  1240. if (disk->pentry_arr_bak)
  1241. free(disk->pentry_arr_bak);
  1242. free(disk);
  1243. return;
  1244. }
  1245. //fills up the passed in gpt_disk struct with information about the
  1246. //disk represented by path dev. Returns 0 on success and -1 on error.
  1247. int gpt_disk_get_disk_info(const char *dev, struct gpt_disk *dsk)
  1248. {
  1249. struct gpt_disk *disk = NULL;
  1250. int fd = -1;
  1251. uint32_t gpt_header_size = 0;
  1252. uint32_t crc_zero;
  1253. crc_zero = crc32(0L, Z_NULL, 0);
  1254. if (!dsk || !dev) {
  1255. ALOGE("%s: Invalid arguments", __func__);
  1256. goto error;
  1257. }
  1258. disk = dsk;
  1259. disk->hdr = gpt_get_header(dev, PRIMARY_GPT);
  1260. if (!disk->hdr) {
  1261. ALOGE("%s: Failed to get primary header", __func__);
  1262. goto error;
  1263. }
  1264. gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
  1265. disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
  1266. disk->hdr_bak = gpt_get_header(dev, SECONDARY_GPT);
  1267. if (!disk->hdr_bak) {
  1268. ALOGE("%s: Failed to get backup header", __func__);
  1269. goto error;
  1270. }
  1271. disk->hdr_bak_crc = crc32(crc_zero, disk->hdr_bak, gpt_header_size);
  1272. //Descriptor for the block device. We will use this for further
  1273. //modifications to the partition table
  1274. if (get_dev_path_from_partition_name(dev,
  1275. disk->devpath,
  1276. sizeof(disk->devpath)) != 0) {
  1277. ALOGE("%s: Failed to resolve path for %s",
  1278. __func__,
  1279. dev);
  1280. goto error;
  1281. }
  1282. fd = open(disk->devpath, O_RDWR);
  1283. if (fd < 0) {
  1284. ALOGE("%s: Failed to open %s: %s",
  1285. __func__,
  1286. disk->devpath,
  1287. strerror(errno));
  1288. goto error;
  1289. }
  1290. disk->pentry_arr = gpt_get_pentry_arr(disk->hdr, fd);
  1291. if (!disk->pentry_arr) {
  1292. ALOGE("%s: Failed to obtain partition entry array",
  1293. __func__);
  1294. goto error;
  1295. }
  1296. disk->pentry_arr_bak = gpt_get_pentry_arr(disk->hdr_bak, fd);
  1297. if (!disk->pentry_arr_bak) {
  1298. ALOGE("%s: Failed to obtain backup partition entry array",
  1299. __func__);
  1300. goto error;
  1301. }
  1302. disk->pentry_size = GET_4_BYTES(disk->hdr + PENTRY_SIZE_OFFSET);
  1303. disk->pentry_arr_size =
  1304. GET_4_BYTES(disk->hdr + PARTITION_COUNT_OFFSET) *
  1305. disk->pentry_size;
  1306. disk->pentry_arr_crc = GET_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET);
  1307. disk->pentry_arr_bak_crc = GET_4_BYTES(disk->hdr_bak +
  1308. PARTITION_CRC_OFFSET);
  1309. disk->block_size = gpt_get_block_size(fd);
  1310. close(fd);
  1311. disk->is_initialized = GPT_DISK_INIT_MAGIC;
  1312. return 0;
  1313. error:
  1314. if (fd >= 0)
  1315. close(fd);
  1316. return -1;
  1317. }
  1318. //Get pointer to partition entry from a allocated gpt_disk structure
  1319. uint8_t* gpt_disk_get_pentry(struct gpt_disk *disk,
  1320. const char *partname,
  1321. enum gpt_instance instance)
  1322. {
  1323. uint8_t *ptn_arr = NULL;
  1324. if (!disk || !partname || disk->is_initialized != GPT_DISK_INIT_MAGIC) {
  1325. ALOGE("%s: Invalid argument",__func__);
  1326. goto error;
  1327. }
  1328. ptn_arr = (instance == PRIMARY_GPT) ?
  1329. disk->pentry_arr : disk->pentry_arr_bak;
  1330. return (gpt_pentry_seek(partname, ptn_arr,
  1331. ptn_arr + disk->pentry_arr_size ,
  1332. disk->pentry_size));
  1333. error:
  1334. return NULL;
  1335. }
  1336. //Update CRC values for the various components of the gpt_disk
  1337. //structure. This function should be called after any of the fields
  1338. //have been updated before the structure contents are written back to
  1339. //disk.
  1340. int gpt_disk_update_crc(struct gpt_disk *disk)
  1341. {
  1342. uint32_t gpt_header_size = 0;
  1343. uint32_t crc_zero;
  1344. crc_zero = crc32(0L, Z_NULL, 0);
  1345. if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)) {
  1346. ALOGE("%s: invalid argument", __func__);
  1347. goto error;
  1348. }
  1349. //Recalculate the CRC of the primary partiton array
  1350. disk->pentry_arr_crc = crc32(crc_zero,
  1351. disk->pentry_arr,
  1352. disk->pentry_arr_size);
  1353. //Recalculate the CRC of the backup partition array
  1354. disk->pentry_arr_bak_crc = crc32(crc_zero,
  1355. disk->pentry_arr_bak,
  1356. disk->pentry_arr_size);
  1357. //Update the partition CRC value in the primary GPT header
  1358. PUT_4_BYTES(disk->hdr + PARTITION_CRC_OFFSET, disk->pentry_arr_crc);
  1359. //Update the partition CRC value in the backup GPT header
  1360. PUT_4_BYTES(disk->hdr_bak + PARTITION_CRC_OFFSET,
  1361. disk->pentry_arr_bak_crc);
  1362. //Update the CRC value of the primary header
  1363. gpt_header_size = GET_4_BYTES(disk->hdr + HEADER_SIZE_OFFSET);
  1364. //Header CRC is calculated with its own CRC field set to 0
  1365. PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, 0);
  1366. PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, 0);
  1367. disk->hdr_crc = crc32(crc_zero, disk->hdr, gpt_header_size);
  1368. disk->hdr_bak_crc = crc32(crc_zero, disk->hdr_bak, gpt_header_size);
  1369. PUT_4_BYTES(disk->hdr + HEADER_CRC_OFFSET, disk->hdr_crc);
  1370. PUT_4_BYTES(disk->hdr_bak + HEADER_CRC_OFFSET, disk->hdr_bak_crc);
  1371. return 0;
  1372. error:
  1373. return -1;
  1374. }
  1375. //Write the contents of struct gpt_disk back to the actual disk
  1376. int gpt_disk_commit(struct gpt_disk *disk)
  1377. {
  1378. int fd = -1;
  1379. if (!disk || (disk->is_initialized != GPT_DISK_INIT_MAGIC)){
  1380. ALOGE("%s: Invalid args", __func__);
  1381. goto error;
  1382. }
  1383. fd = open(disk->devpath, O_RDWR | O_DSYNC);
  1384. if (fd < 0) {
  1385. ALOGE("%s: Failed to open %s: %s",
  1386. __func__,
  1387. disk->devpath,
  1388. strerror(errno));
  1389. goto error;
  1390. }
  1391. //Write the primary header
  1392. if(gpt_set_header(disk->hdr, fd, PRIMARY_GPT) != 0) {
  1393. ALOGE("%s: Failed to update primary GPT header",
  1394. __func__);
  1395. goto error;
  1396. }
  1397. //Write back the primary partition array
  1398. if (gpt_set_pentry_arr(disk->hdr, fd, disk->pentry_arr)) {
  1399. ALOGE("%s: Failed to write primary GPT partition arr",
  1400. __func__);
  1401. goto error;
  1402. }
  1403. //Write back the secondary header
  1404. if(gpt_set_header(disk->hdr_bak, fd, SECONDARY_GPT) != 0) {
  1405. ALOGE("%s: Failed to update secondary GPT header",
  1406. __func__);
  1407. goto error;
  1408. }
  1409. //Write back the secondary partition array
  1410. if (gpt_set_pentry_arr(disk->hdr_bak, fd, disk->pentry_arr_bak)) {
  1411. ALOGE("%s: Failed to write secondary GPT partition arr",
  1412. __func__);
  1413. goto error;
  1414. }
  1415. fsync(fd);
  1416. close(fd);
  1417. return 0;
  1418. error:
  1419. if (fd >= 0)
  1420. close(fd);
  1421. return -1;
  1422. }