Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(275)

Unified Diff: src/platform/vboot_reference/utility/cgpt/cgpt.c

Issue 2082015: add cgpt framework and attribute support. (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/platform/vboot_reference/utility/cgpt/cgpt.c
diff --git a/src/platform/vboot_reference/utility/cgpt/cgpt.c b/src/platform/vboot_reference/utility/cgpt/cgpt.c
new file mode 100644
index 0000000000000000000000000000000000000000..e20a2d2640013e770d420fb206ed678fe1b5f717
--- /dev/null
+++ b/src/platform/vboot_reference/utility/cgpt/cgpt.c
@@ -0,0 +1,246 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Utility for ChromeOS-specific GPT partitions, Please see corresponding .c
+ * files for more details.
+ */
+#include "cgpt.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "utility.h"
+
+/* For usage print */
+const char* progname;
+
+/* Lists all command here. */
+struct {
+ const char *name;
+ int (*fp)(int argc, char *argv[]);
+ const char *comment;
+} cmds[] = {
+ {"attribute", CgptAttribute, "Update GPT attribute bits "
+ "(for ChromeOS kernel entry only)"},
+ {"show", CgptShow, "Show partition details"},
+};
+
+/* Shows main menu. If 'message' is non-NULL, shows it as header. Then, this
+ * traverses cmds[] and shows supported commands and their comments. */
+void Usage(const char *message) {
+ int i;
+
+ if (message) printf("%s\n", message);
+ printf("Usage: %s COMMAND [OPTIONS]\n\n"
+ "Supported commands:\n\n",
+ progname);
+ for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
+ printf(" %-10s %s\n", cmds[i].name, cmds[i].comment);
+ }
+ printf("\nFor more detailed usage, use %s COMMAND --help.\n\n", progname);
+}
+
+/* Loads sectors from 'fd'.
+ * *buf is pointed to an allocated memory when returned, and should be
+ * freed by cgpt_close().
+ *
+ * fd -- file descriptot.
+ * buf -- pointer to buffer pointer
+ * sector -- offset of starting sector (in sectors)
+ * sector_bytes -- bytes per sector
+ * sector_count -- number of sectors to load
+ *
+ * Returns CGPT_OK for successful. Aborts if any error occurs.
+ */
+int Load(const int fd, uint8_t **buf,
+ const uint64_t sector,
+ const uint64_t sector_bytes,
+ const uint64_t sector_count) {
+ int count; /* byte count to read */
+ int nread;
+
+ assert(buf);
+ count = sector_bytes * sector_count;
+ *buf = Malloc(count);
+ assert(*buf);
+
+ if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET))
+ goto error_free;
+
+ nread = read(fd, *buf, count);
+ if (nread < count)
+ goto error_free;
+
+ return CGPT_OK;
+
+error_free:
+ Free(*buf);
+ *buf = 0;
+ abort();
+}
+
+/* Saves sectors to 'fd'.
+ *
+ * fd -- file descriptot.
+ * buf -- pointer to buffer
+ * sector -- starting sector offset
+ * sector_bytes -- bytes per sector
+ * sector_count -- number of sector to save
+ *
+ * Returns CGPT_OK for successful, CGPT_FAILED for failed.
+ */
+int Save(const int fd, const uint8_t *buf,
+ const uint64_t sector,
+ const uint64_t sector_bytes,
+ const uint64_t sector_count) {
+ int count; /* byte count to write */
+ int nwrote;
+
+ assert(buf);
+ count = sector_bytes * sector_count;
+
+ if (-1 == lseek(fd, sector * sector_bytes, SEEK_SET))
+ return CGPT_FAILED;
+
+ nwrote = write(fd, buf, count);
+ if (nwrote < count)
+ return CGPT_FAILED;
+
+ return CGPT_OK;
+}
+
+/* Opens a block device (a regular file works well too).
+ *
+ * Returns CGPT_FAILED if any error happens.
+ * Returns CGPT_OK if success and information are stored in 'drive'. */
+int DriveOpen(const char *drive_path, struct drive *drive) {
+ struct stat stat;
+ int gpt_retval;
+
+ assert(drive_path);
+ assert(drive);
+
+ Memset(drive, 0, sizeof(struct drive));
+ drive->fd = open(drive_path, O_RDWR);
+ if (drive->fd == -1) {
+ printf("[ERROR] Cannot open drive file [%s]: %s\n",
+ drive_path, strerror(errno));
+ return CGPT_FAILED;
+ }
+
+ if (fstat(drive->fd, &stat) == -1) {
+ goto error_close;
+ }
+ if ((stat.st_mode & S_IFMT) != S_IFREG) {
+ if (ioctl(drive->fd, BLKGETSIZE64, &drive->size) < 0) {
+ printf("[ERROR] Cannot get sector size from drive file [%s]: %s\n",
+ drive_path, strerror(errno));
+ goto error_close;
+ }
+ if (ioctl(drive->fd, BLKSSZGET, &drive->gpt.sector_bytes) < 0) {
+ printf("[ERROR] Cannot get drive size from drive file [%s]: %s\n",
+ drive_path, strerror(errno));
+ goto error_close;
+ }
+ } else {
+ drive->gpt.sector_bytes = 512; /* bytes */
+ drive->size = stat.st_size;
+ }
+ if (drive->size % drive->gpt.sector_bytes) {
+ printf("[ERROR] Media size (%llu) is not the multiple of sector size(%d)\n",
+ (long long unsigned int)drive->size, drive->gpt.sector_bytes);
+ goto error_close;
+ }
+ drive->gpt.drive_sectors = drive->size / drive->gpt.sector_bytes;
+ debug("drive: size:%llu sector_size:%d num_sector:%llu\n",
+ (long long unsigned int)drive->size, drive->gpt.sector_bytes,
+ (long long unsigned int)drive->gpt.drive_sectors);
+
+ Load(drive->fd, &drive->gpt.primary_header, GPT_PMBR_SECTOR,
+ drive->gpt.sector_bytes, GPT_HEADER_SECTOR);
+ Load(drive->fd, &drive->gpt.secondary_header,
+ drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
+ drive->gpt.sector_bytes, GPT_HEADER_SECTOR);
+ Load(drive->fd, &drive->gpt.primary_entries,
+ GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
+ drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS);
+ Load(drive->fd, &drive->gpt.secondary_entries,
+ drive->gpt.drive_sectors - GPT_HEADER_SECTOR - GPT_ENTRIES_SECTORS,
+ drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS);
+
+ if (GPT_SUCCESS != (gpt_retval = GptInit(&drive->gpt))) {
+ printf("[ERROR] GptInit(): %s\n", GptError(gpt_retval));
+ goto error_close;
+ }
+
+ drive->inited = 1;
+
+ return CGPT_OK;
+
+error_close:
+ close(drive->fd);
+ return CGPT_FAILED;
+}
+
+int DriveClose(struct drive *drive) {
+ if (drive->inited) {
+ if (drive->gpt.modified & GPT_MODIFIED_HEADER1)
+ assert(CGPT_OK ==
+ Save(drive->fd, drive->gpt.primary_header, GPT_PMBR_SECTOR,
+ drive->gpt.sector_bytes, GPT_HEADER_SECTOR));
+ if (drive->gpt.modified & GPT_MODIFIED_HEADER2)
+ assert(CGPT_OK ==
+ Save(drive->fd, drive->gpt.secondary_header,
+ drive->gpt.drive_sectors - GPT_PMBR_SECTOR,
+ drive->gpt.sector_bytes, GPT_HEADER_SECTOR));
+ if (drive->gpt.modified & GPT_MODIFIED_ENTRIES1)
+ assert(CGPT_OK ==
+ Save(drive->fd, drive->gpt.primary_entries,
+ GPT_PMBR_SECTOR + GPT_HEADER_SECTOR,
+ drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS));
+ if (drive->gpt.modified & GPT_MODIFIED_ENTRIES2)
+ assert(CGPT_OK ==
+ Save(drive->fd, drive->gpt.secondary_entries,
+ drive->gpt.drive_sectors - GPT_HEADER_SECTOR -
+ GPT_ENTRIES_SECTORS,
+ drive->gpt.sector_bytes, GPT_ENTRIES_SECTORS));
+
+ close(drive->fd);
+ }
+
+ Free(drive->gpt.primary_header);
+ drive->gpt.primary_header = 0;
+ Free(drive->gpt.primary_entries);
+ drive->gpt.primary_entries = 0;
+ Free(drive->gpt.secondary_header);
+ drive->gpt.secondary_header = 0;
+ Free(drive->gpt.secondary_entries);
+ drive->gpt.secondary_entries = 0;
+
+ drive->inited = 0;
+ return CGPT_OK;
+}
+
+int main(int argc, char *argv[]) {
+ char *cmd;
+ int i;
+
+ progname = argv[0];
+ cmd = argv[optind++];
+ for (i = 0; i < sizeof(cmds)/sizeof(cmds[0]); ++i) {
+ if (cmd && !strcmp(cmds[i].name, cmd))
+ return cmds[i].fp(argc, argv);
+ }
+
+ Usage(0);
+ return CGPT_FAILED;
+}

Powered by Google App Engine
This is Rietveld 408576698