xref: /aosp_15_r20/external/vboot_reference/cgpt/cgpt_boot.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2012 The ChromiumOS Authors
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  */
5 
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <unistd.h>
10 
11 #include "cgpt.h"
12 #include "cgptlib_internal.h"
13 #include "cgpt_params.h"
14 #include "vboot_host.h"
15 
CgptGetBootPartitionNumber(CgptBootParams * params)16 int CgptGetBootPartitionNumber(CgptBootParams *params) {
17   struct drive drive;
18   int gpt_retval= 0;
19   int retval;
20 
21   if (params == NULL)
22     return CGPT_FAILED;
23 
24   if (CGPT_OK != DriveOpen(params->drive_name, &drive, O_RDONLY,
25                            params->drive_size))
26     return CGPT_FAILED;
27 
28   if (GPT_SUCCESS != (gpt_retval = GptValidityCheck(&drive.gpt))) {
29     Error("GptValidityCheck() returned %d: %s\n",
30           gpt_retval, GptError(gpt_retval));
31     retval = CGPT_FAILED;
32     goto done;
33   }
34 
35   if (CGPT_OK != ReadPMBR(&drive)) {
36     Error("Unable to read PMBR\n");
37     retval = CGPT_FAILED;
38     goto done;
39   }
40 
41   char buf[GUID_STRLEN];
42   GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
43 
44   int numEntries = GetNumberOfEntries(&drive);
45   int i;
46   for (i = 0; i < numEntries; i++) {
47       GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, i);
48 
49       if (GuidEqual(&entry->unique, &drive.pmbr.boot_guid)) {
50         params->partition = i + 1;
51         retval = CGPT_OK;
52         goto done;
53       }
54   }
55 
56   Error("Didn't find any boot partition\n");
57   params->partition = 0;
58   retval = CGPT_FAILED;
59 
60 done:
61   (void) DriveClose(&drive, 1);
62   return retval;
63 }
64 
65 
CgptBoot(CgptBootParams * params)66 int CgptBoot(CgptBootParams *params) {
67   struct drive drive;
68   int retval = 1;
69   int gpt_retval= 0;
70   int mode = O_RDONLY;
71 
72   if (params == NULL)
73     return CGPT_FAILED;
74 
75   if (params->create_pmbr || params->partition || params->bootfile)
76     mode = O_RDWR;
77 
78   if (CGPT_OK != DriveOpen(params->drive_name, &drive, mode,
79                            params->drive_size)) {
80     return CGPT_FAILED;
81   }
82 
83   if (CGPT_OK != ReadPMBR(&drive)) {
84     Error("Unable to read PMBR\n");
85     goto done;
86   }
87 
88   if (params->create_pmbr) {
89     drive.pmbr.magic[0] = 0x1d;
90     drive.pmbr.magic[1] = 0x9a;
91     drive.pmbr.sig[0] = 0x55;
92     drive.pmbr.sig[1] = 0xaa;
93     memset(&drive.pmbr.part, 0, sizeof(drive.pmbr.part));
94     drive.pmbr.part[0].f_head = 0x00;
95     drive.pmbr.part[0].f_sect = 0x02;
96     drive.pmbr.part[0].f_cyl = 0x00;
97     drive.pmbr.part[0].type = 0xee;
98     drive.pmbr.part[0].l_head = 0xff;
99     drive.pmbr.part[0].l_sect = 0xff;
100     drive.pmbr.part[0].l_cyl = 0xff;
101     drive.pmbr.part[0].f_lba = htole32(1);
102     uint32_t max = 0xffffffff;
103     if (drive.gpt.streaming_drive_sectors < 0xffffffff)
104       max = drive.gpt.streaming_drive_sectors - 1;
105     drive.pmbr.part[0].num_sect = htole32(max);
106   }
107 
108   if (params->partition) {
109     if (GPT_SUCCESS != (gpt_retval = GptValidityCheck(&drive.gpt))) {
110       Error("GptValidityCheck() returned %d: %s\n",
111             gpt_retval, GptError(gpt_retval));
112       goto done;
113     }
114 
115     if (params->partition > GetNumberOfEntries(&drive)) {
116       Error("invalid partition number: %d\n", params->partition);
117       goto done;
118     }
119 
120     uint32_t index = params->partition - 1;
121     GptEntry *entry = GetEntry(&drive.gpt, ANY_VALID, index);
122     memcpy(&drive.pmbr.boot_guid, &entry->unique, sizeof(Guid));
123   }
124 
125   if (params->bootfile) {
126     int fd = open(params->bootfile, O_RDONLY);
127     if (fd < 0) {
128       Error("Can't read %s: %s\n", params->bootfile, strerror(errno));
129       goto done;
130     }
131 
132     int n = read(fd, drive.pmbr.bootcode, sizeof(drive.pmbr.bootcode));
133     if (n < 1) {
134       Error("problem reading %s: %s\n", params->bootfile, strerror(errno));
135       close(fd);
136       goto done;
137     }
138 
139     close(fd);
140   }
141 
142   char buf[GUID_STRLEN];
143   GuidToStr(&drive.pmbr.boot_guid, buf, sizeof(buf));
144   printf("%s\n", buf);
145 
146   // Write it all out, if needed.
147   if (mode == O_RDONLY || CGPT_OK == WritePMBR(&drive))
148     retval = 0;
149 
150 done:
151   (void) DriveClose(&drive, 1);
152   return retval;
153 }
154