bootinfo.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (C) 2015 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <errno.h>
  17. #include <fcntl.h>
  18. #include <linux/fs.h>
  19. #include <sys/ioctl.h>
  20. #include <sys/stat.h>
  21. #include <sys/types.h>
  22. #include <unistd.h>
  23. #include <arpa/inet.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <bootloader_message/bootloader_message.h>
  28. #include <cutils/properties.h>
  29. #include <fs_mgr.h>
  30. #include "bootinfo.h"
  31. using android::fs_mgr::Fstab;
  32. using android::fs_mgr::GetEntryForMountPoint;
  33. using android::fs_mgr::ReadDefaultFstab;
  34. using android::fs_mgr::ReadFstabFromFile;
  35. // Open the appropriate fstab file and fallback to /fstab.device if
  36. // that's what's being used.
  37. static bool open_fstab(Fstab* fstab)
  38. {
  39. return ReadDefaultFstab(fstab) || ReadFstabFromFile("/fstab.device", fstab);
  40. }
  41. int boot_info_open_partition(const char *name, uint64_t *out_size, int flags)
  42. {
  43. char *path;
  44. int fd;
  45. // We can't use fs_mgr to look up |name| because fstab doesn't list
  46. // every slot partition (it uses the slotselect option to mask the
  47. // suffix) and |slot| is expected to be of that form, e.g. boot_a.
  48. //
  49. // We can however assume that there's an entry for the /misc mount
  50. // point and use that to get the device file for the misc
  51. // partition. From there we'll assume that a by-name scheme is used
  52. // so we can just replace the trailing "misc" by the given |name|,
  53. // e.g.
  54. //
  55. // /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
  56. // /dev/block/platform/soc.0/7824900.sdhci/by-name/boot_a
  57. //
  58. // If needed, it's possible to relax this assumption in the future
  59. // by trawling /sys/block looking for the appropriate sibling of
  60. // misc and then finding an entry in /dev matching the sysfs entry.
  61. Fstab fstab;
  62. if (!open_fstab(&fstab)) {
  63. return -1;
  64. }
  65. auto record = GetEntryForMountPoint(&fstab, "/misc");
  66. if (record == nullptr) {
  67. return -1;
  68. }
  69. if (strcmp(name, "misc") == 0) {
  70. path = strdup(record->blk_device.c_str());
  71. } else {
  72. size_t trimmed_len, name_len;
  73. const char *end_slash = strrchr(record->blk_device.c_str(), '/');
  74. if (end_slash == NULL) {
  75. return -1;
  76. }
  77. trimmed_len = end_slash - record->blk_device.c_str() + 1;
  78. name_len = strlen(name);
  79. path = static_cast<char *>(calloc(trimmed_len + name_len + 1, 1));
  80. strncpy(path, record->blk_device.c_str(), trimmed_len);
  81. strncpy(path + trimmed_len, name, name_len);
  82. }
  83. fd = open(path, flags);
  84. free(path);
  85. // If we successfully opened the device, get size if requested.
  86. if (fd != -1 && out_size != NULL) {
  87. if (ioctl(fd, BLKGETSIZE64, out_size) != 0) {
  88. close(fd);
  89. return -1;
  90. }
  91. }
  92. return fd;
  93. }
  94. // As per struct bootloader_message_ab which is defined in
  95. // bootable/recovery/bootloader.h we can use the 32 bytes in the
  96. // bootctrl_suffix field provided that they start with the active slot
  97. // suffix terminated by NUL. It just so happens that BrilloBootInfo is
  98. // laid out this way.
  99. #define BOOTINFO_OFFSET offsetof(struct bootloader_message_ab, slot_suffix)
  100. bool boot_info_load(BrilloBootInfo *out_info)
  101. {
  102. int fd;
  103. memset(out_info, '\0', sizeof(BrilloBootInfo));
  104. fd = boot_info_open_partition("misc", NULL, O_RDONLY);
  105. if (fd == -1)
  106. return false;
  107. if (lseek(fd, BOOTINFO_OFFSET, SEEK_SET) != BOOTINFO_OFFSET) {
  108. close(fd);
  109. return false;
  110. }
  111. ssize_t num_read;
  112. do {
  113. num_read = read(fd, (void*) out_info, sizeof(BrilloBootInfo));
  114. } while (num_read == -1 && errno == EINTR);
  115. close(fd);
  116. if (num_read != sizeof(BrilloBootInfo))
  117. return false;
  118. return true;
  119. }
  120. bool boot_info_save(BrilloBootInfo *info)
  121. {
  122. int fd;
  123. fd = boot_info_open_partition("misc", NULL, O_RDWR);
  124. if (fd == -1)
  125. return false;
  126. if (lseek(fd, BOOTINFO_OFFSET, SEEK_SET) != BOOTINFO_OFFSET) {
  127. close(fd);
  128. return false;
  129. }
  130. ssize_t num_written;
  131. do {
  132. num_written = write(fd, (void*) info, sizeof(BrilloBootInfo));
  133. } while (num_written == -1 && errno == EINTR);
  134. close(fd);
  135. if (num_written != sizeof(BrilloBootInfo))
  136. return false;
  137. return true;
  138. }
  139. bool boot_info_validate(BrilloBootInfo* info)
  140. {
  141. if (info->magic[0] != 'B' ||
  142. info->magic[1] != 'C' ||
  143. info->magic[2] != 'c')
  144. return false;
  145. if (info->active_slot >= 2)
  146. return false;
  147. return true;
  148. }
  149. void boot_info_reset(BrilloBootInfo* info)
  150. {
  151. memset(info, '\0', sizeof(BrilloBootInfo));
  152. info->magic[0] = 'B';
  153. info->magic[1] = 'C';
  154. info->magic[2] = 'c';
  155. }