1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
6 #define VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
7 
8 #include <fcntl.h>
9 #ifndef HAVE_MACOS
10 #include <features.h>
11 #endif
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include "cgpt_endian.h"
16 #include "cgptlib.h"
17 #include "gpt.h"
18 
19 struct legacy_partition {
20   uint8_t  status;
21   uint8_t  f_head;
22   uint8_t  f_sect;
23   uint8_t  f_cyl;
24   uint8_t  type;
25   uint8_t  l_head;
26   uint8_t  l_sect;
27   uint8_t  l_cyl;
28   uint32_t f_lba;
29   uint32_t num_sect;
30 } __attribute__((packed));
31 
32 // syslinux uses this format:
33 struct pmbr {
34   uint8_t                 bootcode[424];
35   Guid                    boot_guid;
36   uint32_t                disk_id;
37   uint8_t                 magic[2];     // 0x1d, 0x9a
38   struct legacy_partition part[4];
39   uint8_t                 sig[2];       // 0x55, 0xaa
40 } __attribute__((packed));
41 
42 void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen);
43 
44 // Handle to the drive storing the GPT.
45 struct drive {
46   uint64_t size;    /* total size (in bytes) */
47   GptData gpt;
48   struct pmbr pmbr;
49   int fd;       /* file descriptor */
50 };
51 
52 // Opens a block device or file, loads raw GPT data from it.
53 // 'mode' should be O_RDONLY or O_RDWR.
54 // If 'drive_size' is 0, both the partitions and GPT structs reside on the same
55 // 'drive_path'.
56 // Otherwise, 'drive_size' is taken as the size of the device that all
57 // partitions will reside on, and 'drive_path' is where we store GPT structs.
58 //
59 // Returns CGPT_FAILED if any error happens.
60 // Returns CGPT_OK if success and information are stored in 'drive'. */
61 int DriveOpen(const char *drive_path, struct drive *drive, int mode,
62               uint64_t drive_size);
63 int DriveClose(struct drive *drive, int update_as_needed);
64 int CheckValid(const struct drive *drive);
65 
66 /* Loads sectors from 'drive'.
67  * *buf is pointed to an allocated memory when returned, and should be
68  * freed.
69  *
70  *   drive -- open drive.
71  *   buf -- pointer to buffer pointer
72  *   sector -- offset of starting sector (in sectors)
73  *   sector_bytes -- bytes per sector
74  *   sector_count -- number of sectors to load
75  *
76  * Returns CGPT_OK for successful. Aborts if any error occurs.
77  */
78 int Load(struct drive *drive, uint8_t **buf,
79                 const uint64_t sector,
80                 const uint64_t sector_bytes,
81                 const uint64_t sector_count);
82 
83 /* Saves sectors to 'drive'.
84  *
85  *   drive -- open drive
86  *   buf -- pointer to buffer
87  *   sector -- starting sector offset
88  *   sector_bytes -- bytes per sector
89  *   sector_count -- number of sector to save
90  *
91  * Returns CGPT_OK for successful, CGPT_FAILED for failed.
92  */
93 int Save(struct drive *drive, const uint8_t *buf,
94                 const uint64_t sector,
95                 const uint64_t sector_bytes,
96                 const uint64_t sector_count);
97 
98 
99 /* GUID conversion functions. Accepted format:
100  *
101  *   "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
102  *
103  * At least GUID_STRLEN bytes should be reserved in 'str' (included the tailing
104  * '\0').
105  */
106 #define GUID_STRLEN 37
107 int StrToGuid(const char *str, Guid *guid);
108 void GuidToStr(const Guid *guid, char *str, unsigned int buflen);
109 int GuidEqual(const Guid *guid1, const Guid *guid2);
110 int IsZero(const Guid *guid);
111 
112 /* Constant global type values to compare against */
113 extern const Guid guid_chromeos_firmware;
114 extern const Guid guid_chromeos_kernel;
115 extern const Guid guid_chromeos_rootfs;
116 extern const Guid guid_linux_data;
117 extern const Guid guid_chromeos_reserved;
118 extern const Guid guid_efi;
119 extern const Guid guid_unused;
120 
121 int ReadPMBR(struct drive *drive);
122 int WritePMBR(struct drive *drive);
123 
124 /* Convert possibly unterminated UTF16 string to UTF8.
125  * Caller must prepare enough space for UTF8, which could be up to
126  * twice the byte length of UTF16 string plus the terminating '\0'.
127  *
128  * Return: CGPT_OK --- all character are converted successfully.
129  *         CGPT_FAILED --- convert error, i.e. output buffer is too short.
130  */
131 int UTF16ToUTF8(const uint16_t *utf16, unsigned int maxinput,
132                 uint8_t *utf8, unsigned int maxoutput);
133 
134 /* Convert null-terminated UTF8 string to UTF16.
135  * Caller must prepare enough space for UTF16, which is the byte length of UTF8
136  * plus the terminating 0x0000.
137  *
138  * Return: CGPT_OK --- all character are converted successfully.
139  *         CGPT_FAILED --- convert error, i.e. output buffer is too short.
140  */
141 int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput);
142 
143 /* Helper functions for supported GPT types. */
144 int ResolveType(const Guid *type, char *buf);
145 int SupportedType(const char *name, Guid *type);
146 void PrintTypes(void);
147 void EntryDetails(GptEntry *entry, uint32_t index, int raw);
148 
149 uint32_t GetNumberOfEntries(const struct drive *drive);
150 GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
151 
152 void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
153                  int priority);
154 int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
155 void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
156               int tries);
157 int GetTries(struct drive *drive, int secondary, uint32_t entry_index);
158 void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
159                    int success);
160 int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index);
161 
162 void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
163            uint32_t raw);
164 
165 void UpdateAllEntries(struct drive *drive);
166 
167 uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers);
168 uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries);
169 void UpdateCrc(GptData *gpt);
170 int IsSynonymous(const GptHeader* a, const GptHeader* b);
171 
172 int IsUnused(struct drive *drive, int secondary, uint32_t index);
173 int IsKernel(struct drive *drive, int secondary, uint32_t index);
174 
175 // Optional. Applications that need this must provide an implementation.
176 //
177 // Explanation:
178 //   Some external utilities need to manipulate the GPT, but don't create new
179 //   partitions from scratch. The cgpt executable uses libuuid to provide this
180 //   functionality, but we don't want to have to build or install a separate
181 //   instance of that library just for the 32-bit static post-install tool,
182 //   which doesn't need this function.
183 int GenerateGuid(Guid *newguid);
184 
185 // For usage and error messages.
186 void Error(const char *format, ...);
187 void Warning(const char *format, ...);
188 
189 // Command functions.
190 int cmd_show(int argc, char *argv[]);
191 int cmd_repair(int argc, char *argv[]);
192 int cmd_create(int argc, char *argv[]);
193 int cmd_add(int argc, char *argv[]);
194 int cmd_boot(int argc, char *argv[]);
195 int cmd_find(int argc, char *argv[]);
196 int cmd_prioritize(int argc, char *argv[]);
197 int cmd_legacy(int argc, char *argv[]);
198 
199 #define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
200 const char *GptError(int errnum);
201 
202 // Size in chars of the GPT Entry's PartitionName field
203 #define GPT_PARTNAME_LEN 72
204 
205 /* The standard "assert" macro goes away when NDEBUG is defined. This doesn't.
206  */
207 #define require(A) do { \
208   if (!(A)) { \
209     fprintf(stderr, "condition (%s) failed at %s:%d\n", \
210             #A, __FILE__, __LINE__); \
211     exit(1); } \
212   } while (0)
213 
214 #endif  // VBOOT_REFERENCE_UTILITY_CGPT_CGPT_H_
215