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
19struct 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:
33struct 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
42void PMBRToStr(struct pmbr *pmbr, char *str, unsigned int buflen);
43
44// Handle to the drive storing the GPT.
45struct 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'. */
61int DriveOpen(const char *drive_path, struct drive *drive, int mode,
62              uint64_t drive_size);
63int DriveClose(struct drive *drive, int update_as_needed);
64int 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 */
78int 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 */
93int 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
107int StrToGuid(const char *str, Guid *guid);
108void GuidToStr(const Guid *guid, char *str, unsigned int buflen);
109int GuidEqual(const Guid *guid1, const Guid *guid2);
110int IsZero(const Guid *guid);
111
112/* Constant global type values to compare against */
113extern const Guid guid_chromeos_firmware;
114extern const Guid guid_chromeos_kernel;
115extern const Guid guid_chromeos_rootfs;
116extern const Guid guid_linux_data;
117extern const Guid guid_chromeos_reserved;
118extern const Guid guid_efi;
119extern const Guid guid_unused;
120
121int ReadPMBR(struct drive *drive);
122int 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 */
131int 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 */
141int UTF8ToUTF16(const uint8_t *utf8, uint16_t *utf16, unsigned int maxoutput);
142
143/* Helper functions for supported GPT types. */
144int ResolveType(const Guid *type, char *buf);
145int SupportedType(const char *name, Guid *type);
146void PrintTypes(void);
147void EntryDetails(GptEntry *entry, uint32_t index, int raw);
148
149uint32_t GetNumberOfEntries(const struct drive *drive);
150GptEntry *GetEntry(GptData *gpt, int secondary, uint32_t entry_index);
151
152void SetPriority(struct drive *drive, int secondary, uint32_t entry_index,
153                 int priority);
154int GetPriority(struct drive *drive, int secondary, uint32_t entry_index);
155void SetTries(struct drive *drive, int secondary, uint32_t entry_index,
156              int tries);
157int GetTries(struct drive *drive, int secondary, uint32_t entry_index);
158void SetSuccessful(struct drive *drive, int secondary, uint32_t entry_index,
159                   int success);
160int GetSuccessful(struct drive *drive, int secondary, uint32_t entry_index);
161
162void SetRaw(struct drive *drive, int secondary, uint32_t entry_index,
163           uint32_t raw);
164
165void UpdateAllEntries(struct drive *drive);
166
167uint8_t RepairHeader(GptData *gpt, const uint32_t valid_headers);
168uint8_t RepairEntries(GptData *gpt, const uint32_t valid_entries);
169void UpdateCrc(GptData *gpt);
170int IsSynonymous(const GptHeader* a, const GptHeader* b);
171
172int IsUnused(struct drive *drive, int secondary, uint32_t index);
173int 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.
183int GenerateGuid(Guid *newguid);
184
185// For usage and error messages.
186void Error(const char *format, ...);
187void Warning(const char *format, ...);
188
189// Command functions.
190int cmd_show(int argc, char *argv[]);
191int cmd_repair(int argc, char *argv[]);
192int cmd_create(int argc, char *argv[]);
193int cmd_add(int argc, char *argv[]);
194int cmd_boot(int argc, char *argv[]);
195int cmd_find(int argc, char *argv[]);
196int cmd_prioritize(int argc, char *argv[]);
197int cmd_legacy(int argc, char *argv[]);
198
199#define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0]))
200const 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