Esempio n. 1
0
grub_err_t
grub_efi_set_variable(const char *var, const grub_efi_guid_t *guid,
		      void *data, grub_size_t datasize)
{
  grub_efi_status_t status;
  grub_efi_runtime_services_t *r;
  grub_efi_char16_t *var16;
  grub_size_t len, len16;

  len = grub_strlen (var);
  len16 = len * GRUB_MAX_UTF16_PER_UTF8;
  var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
  if (!var16)
    return grub_errno;
  len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
  var16[len16] = 0;

  r = grub_efi_system_table->runtime_services;

  status = efi_call_5 (r->set_variable, var16, guid, 
		       (GRUB_EFI_VARIABLE_NON_VOLATILE
			| GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
			| GRUB_EFI_VARIABLE_RUNTIME_ACCESS),
		       datasize, data);
  if (status == GRUB_EFI_SUCCESS)
    return GRUB_ERR_NONE;

  return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
}
Esempio n. 2
0
File: efi.c Progetto: Arvian/GRUB2
void *
grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid,
		       grub_size_t *datasize_out)
{
  grub_efi_status_t status;
  grub_efi_uintn_t datasize = 0;
  grub_efi_runtime_services_t *r;
  grub_efi_char16_t *var16;
  void *data;
  grub_size_t len, len16;

  *datasize_out = 0;

  len = grub_strlen (var);
  len16 = len * GRUB_MAX_UTF16_PER_UTF8;
  var16 = grub_malloc ((len16 + 1) * sizeof (var16[0]));
  if (!var16)
    return NULL;
  len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL);
  var16[len16] = 0;

  r = grub_efi_system_table->runtime_services;

  status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL);

  if (!datasize)
    return NULL;

  data = grub_malloc (datasize);
  if (!data)
    {
      grub_free (var16);
      return NULL;
    }

  status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data);
  grub_free (var16);

  if (status == GRUB_EFI_SUCCESS)
    {
      *datasize_out = datasize;
      return data;
    }

  grub_free (data);
  return NULL;
}
Esempio n. 3
0
File: efi.c Progetto: Arvian/GRUB2
/* Return the array of handles which meet the requirement. If successful,
   the number of handles is stored in NUM_HANDLES. The array is allocated
   from the heap.  */
grub_efi_handle_t *
grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
			grub_efi_guid_t *protocol,
			void *search_key,
			grub_efi_uintn_t *num_handles)
{
  grub_efi_boot_services_t *b;
  grub_efi_status_t status;
  grub_efi_handle_t *buffer;
  grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);

  buffer = grub_malloc (buffer_size);
  if (! buffer)
    return 0;

  b = grub_efi_system_table->boot_services;
  status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
			     &buffer_size, buffer);
  if (status == GRUB_EFI_BUFFER_TOO_SMALL)
    {
      grub_free (buffer);
      buffer = grub_malloc (buffer_size);
      if (! buffer)
	return 0;

      status = efi_call_5 (b->locate_handle, search_type, protocol, search_key,
				 &buffer_size, buffer);
    }

  if (status != GRUB_EFI_SUCCESS)
    {
      grub_free (buffer);
      return 0;
    }

  *num_handles = buffer_size / sizeof (grub_efi_handle_t);
  return buffer;
}
Esempio n. 4
0
static grub_err_t
grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf,
		     grub_size_t size, grub_uint8_t pcr,
		     const char *description)
{
  EFI_TCG2_EVENT *event;
  grub_efi_status_t status;
  grub_efi_tpm2_protocol_t *tpm;

  tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);

  if (!grub_tpm2_present (tpm))
    return 0;

  event =
    grub_zalloc (sizeof (EFI_TCG2_EVENT) + grub_strlen (description) + 1);
  if (!event)
    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
		       N_("cannot allocate TPM event buffer"));

  event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER);
  event->Header.HeaderVersion = 1;
  event->Header.PCRIndex = pcr;
  event->Header.EventType = EV_IPL;
  event->Size =
    sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1;
  grub_memcpy (event->Event, description, grub_strlen (description) + 1);

  status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, buf,
		       (grub_uint64_t) size, event);

  switch (status)
    {
    case GRUB_EFI_SUCCESS:
      return 0;
    case GRUB_EFI_DEVICE_ERROR:
      return grub_error (GRUB_ERR_IO, N_("Command failed"));
    case GRUB_EFI_INVALID_PARAMETER:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
    case GRUB_EFI_BUFFER_TOO_SMALL:
      return grub_error (GRUB_ERR_BAD_ARGUMENT,
			 N_("Output buffer too small"));
    case GRUB_EFI_NOT_FOUND:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
    default:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
    }
}
Esempio n. 5
0
static grub_efi_boolean_t grub_tpm_present(grub_efi_tpm_protocol_t *tpm)
{
  grub_efi_status_t status;
  TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
  grub_uint32_t flags;
  grub_efi_physical_address_t eventlog, lastevent;

  caps.Size = (grub_uint8_t)sizeof(caps);

  status = efi_call_5(tpm->status_check, tpm, &caps, &flags, &eventlog,
		      &lastevent);

  if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag
      || !caps.TPMPresentFlag)
    return 0;

  return 1;
}
Esempio n. 6
0
static grub_err_t
grub_tpm2_execute (grub_efi_handle_t tpm_handle,
                   PassThroughToTPM_InputParamBlock *inbuf,
                   PassThroughToTPM_OutputParamBlock *outbuf)
{
  grub_efi_status_t status;
  grub_efi_tpm2_protocol_t *tpm;
  grub_uint32_t inhdrsize = sizeof (*inbuf) - sizeof (inbuf->TPMOperandIn);
  grub_uint32_t outhdrsize =
    sizeof (*outbuf) - sizeof (outbuf->TPMOperandOut);

  tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
				GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);

  if (!grub_tpm2_present (tpm))
    return 0;

  /* UEFI TPM protocol takes the raw operand block, no param block header. */
  status = efi_call_5 (tpm->submit_command, tpm,
		       inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn,
		       outbuf->OPBLength - outhdrsize, outbuf->TPMOperandOut);

  switch (status)
    {
    case GRUB_EFI_SUCCESS:
      return 0;
    case GRUB_EFI_DEVICE_ERROR:
      return grub_error (GRUB_ERR_IO, N_("Command failed"));
    case GRUB_EFI_INVALID_PARAMETER:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
    case GRUB_EFI_BUFFER_TOO_SMALL:
      return grub_error (GRUB_ERR_BAD_ARGUMENT,
			 N_("Output buffer too small"));
    case GRUB_EFI_NOT_FOUND:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
    default:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
    }
}
Esempio n. 7
0
grub_err_t
grub_tpm_log_event(unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
		   const char *description)
{
  grub_efi_handle_t tpm_handle;
  grub_efi_status_t status;
  grub_efi_tpm_protocol_t *tpm;
  grub_efi_tpm2_protocol_t *tpm2;
  grub_efi_physical_address_t lastevent;
  grub_efi_uint8_t protocol_version;
  grub_uint32_t eventnum = 0;
  grub_uint32_t algorithm;
  Event *event;
  EFI_TCG2_EVENT *event2;

  if (!grub_tpm_handle_find(&tpm_handle, &protocol_version)) {
    return 0;
  }

  if (protocol_version == 1) {
    tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid,
				  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);

    if (!grub_tpm_present(tpm)) {
      return 0;
    }

    event = grub_zalloc(sizeof (Event) + grub_strlen(description) + 1);
    if (!event) {
      grub_printf("No buffer\n");
      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			 N_("cannot allocate TPM event buffer"));
    }

    event->pcrindex = pcr;
    event->eventtype = 0x0d;
    event->eventsize = grub_strlen(description) + 1;
    grub_memcpy(event->event, description, event->eventsize);

    algorithm = 0x00000004; /* SHA 1 */
    status = efi_call_7 (tpm->log_extend_event, tpm, buf, (grub_uint64_t) size,
			 algorithm, event, &eventnum, &lastevent);

    switch (status) {
    case GRUB_EFI_SUCCESS:
      return 0;
    case GRUB_EFI_DEVICE_ERROR:
      return grub_error (GRUB_ERR_IO, N_("Command failed"));
    case GRUB_EFI_INVALID_PARAMETER:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
    case GRUB_EFI_BUFFER_TOO_SMALL:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
    case GRUB_EFI_NOT_FOUND:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
    default:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
    }
  } else {
    tpm2 = grub_efi_open_protocol (tpm_handle, &tpm2_guid,
				   GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);

    if (!grub_tpm2_present(tpm2)) {
      return 0;
    }

    event2 = grub_zalloc(sizeof (Event) + grub_strlen(description) + 1);
    if (!event2) {
      grub_printf("No buffer\n");
      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
			 N_("cannot allocate TPM event buffer"));
    }

    event2->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
    event2->Header.HeaderVersion = 1;
    event2->Header.PCRIndex = pcr;
    event2->Header.EventType = 0x0d;
    event2->Size = sizeof(*event2) - sizeof(event2->Event) + grub_strlen(description) + 1;
    grub_memcpy(event2->Event, description, grub_strlen(description) + 1);

    status = efi_call_5 (tpm2->hash_log_extend_event, tpm2, 0, buf,
			 (grub_uint64_t) size, event2);

    switch (status) {
    case GRUB_EFI_SUCCESS:
      return 0;
    case GRUB_EFI_DEVICE_ERROR:
      return grub_error (GRUB_ERR_IO, N_("Command failed"));
    case GRUB_EFI_INVALID_PARAMETER:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
    case GRUB_EFI_BUFFER_TOO_SMALL:
      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
    case GRUB_EFI_NOT_FOUND:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
    default:
      return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
    }
  }
}