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