Esempio n. 1
0
/* Read the recovery reason.  Returns the reason code or -1 if error. */
static int VbGetRecoveryReason(void) {
  unsigned value;

  /* Try reading type from BINF.4 */
  if (ReadFileInt(ACPI_BINF_PATH ".4", &value) == 0)
    return value;

  /* Fall back to BINF.0 for legacy systems like Mario. */
  if (ReadFileInt(ACPI_BINF_PATH ".0", &value) < 0)
    return -1;
  switch(value) {
    case BINF0_NORMAL:
    case BINF0_DEVELOPER:
      return VBNV_RECOVERY_NOT_REQUESTED;
    case BINF0_RECOVERY_BUTTON:
      return VBNV_RECOVERY_RO_MANUAL;
    case BINF0_RECOVERY_DEV_SCREEN_KEY:
      return VBNV_RECOVERY_RW_DEV_SCREEN;
    case BINF0_RECOVERY_RW_FW_BAD:
      return VBNV_RECOVERY_RO_INVALID_RW;
    case BINF0_RECOVERY_NO_OS:
      return VBNV_RECOVERY_RW_NO_OS;
    case BINF0_RECOVERY_BAD_OS:
      return VBNV_RECOVERY_RW_INVALID_OS;
    case BINF0_RECOVERY_OS_INITIATED:
      return VBNV_RECOVERY_LEGACY;
    default:
      /* Other values don't map cleanly to firmware type. */
      return -1;
  }
}
Esempio n. 2
0
int VbReadNvStorage(VbNvContext* vnc) {
  unsigned offs, blksz;

  /* Get the byte offset from VBNV */
  if (ReadFileInt(ACPI_VBNV_PATH ".0", &offs) < 0)
    return -1;
  if (ReadFileInt(ACPI_VBNV_PATH ".1", &blksz) < 0)
    return -1;
  if (VBNV_BLOCK_SIZE > blksz)
    return -1;  /* NV storage block is too small */

  if (0 != VbCmosRead(offs, VBNV_BLOCK_SIZE, vnc->raw))
    return -1;

  return 0;
}
Esempio n. 3
0
const char* VbGetArchPropertyString(const char* name, char* dest,
                                    size_t size) {
  unsigned value;

  if (!strcasecmp(name,"arch")) {
    return StrCopy(dest, "x86", size);
  } else if (!strcasecmp(name,"hwid")) {
    return ReadFileString(dest, size, ACPI_BASE_PATH "/HWID");
  } else if (!strcasecmp(name,"fwid")) {
    return ReadFileString(dest, size, ACPI_BASE_PATH "/FWID");
  } else if (!strcasecmp(name,"ro_fwid")) {
    return ReadFileString(dest, size, ACPI_BASE_PATH "/FRID");
  } else if (!strcasecmp(name,"mainfw_act")) {
    if (ReadFileInt(ACPI_BINF_PATH ".1", &value) < 0)
      return NULL;
    switch(value) {
      case 0:
        return StrCopy(dest, "recovery", size);
      case 1:
        return StrCopy(dest, "A", size);
      case 2:
        return StrCopy(dest, "B", size);
      default:
        return NULL;
    }
  } else if (!strcasecmp(name,"mainfw_type")) {
    return VbReadMainFwType(dest, size);
  } else if (!strcasecmp(name,"ecfw_act")) {
    if (ReadFileInt(ACPI_BINF_PATH ".2", &value) < 0)
      return NULL;
    switch(value) {
      case 0:
        return StrCopy(dest, "RO", size);
      case 1:
        return StrCopy(dest, "RW", size);
      default:
        return NULL;
    }
  } else if (!strcasecmp(name,"platform_family")) {
    return ReadPlatformFamilyString(dest, size);
  }

  return NULL;
}
Esempio n. 4
0
/* Read the active main firmware type into the destination buffer.
 * Passed the destination and its size.  Returns the destination, or
 * NULL if error. */
static const char* VbReadMainFwType(char* dest, int size) {
  unsigned value;

  /* Try reading type from BINF.3 */
  if (ReadFileInt(ACPI_BINF_PATH ".3", &value) == 0) {
    switch(value) {
      case BINF3_NETBOOT:
        return StrCopy(dest, "netboot", size);
      case BINF3_RECOVERY:
        return StrCopy(dest, "recovery", size);
      case BINF3_NORMAL:
        return StrCopy(dest, "normal", size);
      case BINF3_DEVELOPER:
        return StrCopy(dest, "developer", size);
      default:
        break;  /* Fall through to legacy handling */
    }
  }

  /* Fall back to BINF.0 for legacy systems like Mario. */
  if (ReadFileInt(ACPI_BINF_PATH ".0", &value) < 0)
    /* Both BINF.0 and BINF.3 are missing, so this isn't Chrome OS
     * firmware. */
    return StrCopy(dest, "nonchrome", size);

  switch(value) {
    case BINF0_NORMAL:
      return StrCopy(dest, "normal", size);
    case BINF0_DEVELOPER:
      return StrCopy(dest, "developer", size);
    case BINF0_RECOVERY_BUTTON:
    case BINF0_RECOVERY_DEV_SCREEN_KEY:
    case BINF0_RECOVERY_RW_FW_BAD:
    case BINF0_RECOVERY_NO_OS:
    case BINF0_RECOVERY_BAD_OS:
    case BINF0_RECOVERY_OS_INITIATED:
    case BINF0_RECOVERY_TPM_ERROR:
      /* Assorted flavors of recovery boot reason. */
      return StrCopy(dest, "recovery", size);
    default:
      /* Other values don't map cleanly to firmware type. */
      return NULL;
  }
}
Esempio n. 5
0
int VbWriteNvStorage(VbNvContext* vnc) {
  unsigned offs, blksz;

  if (!vnc->raw_changed)
    return 0;  /* Nothing changed, so no need to write */

  /* Get the byte offset from VBNV */
  if (ReadFileInt(ACPI_VBNV_PATH ".0", &offs) < 0)
    return -1;
  if (ReadFileInt(ACPI_VBNV_PATH ".1", &blksz) < 0)
    return -1;
  if (VBNV_BLOCK_SIZE > blksz)
    return -1;  /* NV storage block is too small */

  if (0 != VbCmosWrite(offs, VBNV_BLOCK_SIZE, vnc->raw))
    return -1;

  return 0;
}
Esempio n. 6
0
/* Read the CMOS reboot field in NVRAM.
 *
 * Returns 0 if the mask is clear in the field, 1 if set, or -1 if error. */
static int VbGetCmosRebootField(uint8_t mask) {
  unsigned chnv;
  uint8_t nvbyte;

  /* Get the byte offset from CHNV */
  if (ReadFileInt(ACPI_CHNV_PATH, &chnv) < 0)
    return -1;

  if (0 != VbCmosRead(chnv, 1, &nvbyte))
    return -1;

  return (nvbyte & mask ? 1 : 0);
}
Esempio n. 7
0
/* BayTrail has 3 sets of GPIO banks. It is expected the firmware exposes
 * each bank of gpios using a UID in ACPI. Furthermore the gpio number exposed
 * is relative to the bank. e.g. gpio 6 in the bank specified by UID 3 would
 * be encoded as 0x2006.
 *  UID | Bank Offset
 *  ----+------------
 *   1  | 0x0000
 *   2  | 0x1000
 *   3  | 0x2000
 */
static int BayTrailFindGpioChipOffset(unsigned *gpio_num, unsigned *offset,
                                      const char *name) {
  DIR *dir;
  struct dirent *ent;
  unsigned expected_uid;
  int match = 0;

  /* Obtain relative GPIO number. */
  if (*gpio_num >= 0x2000) {
    *gpio_num -= 0x2000;
    expected_uid = 3;
  } else if (*gpio_num >= 0x1000) {
    *gpio_num -= 0x1000;
    expected_uid = 2;
  } else {
    *gpio_num -= 0x0000;
    expected_uid = 1;
  }

  dir = opendir(GPIO_BASE_PATH);
  if (!dir) {
    return 0;
  }

  while(0 != (ent = readdir(dir))) {
    /* For every gpiochip entry determine uid. */
    if (1 == sscanf(ent->d_name, "gpiochip%u", offset)) {
      char uid_file[128];
      unsigned uid_value;
      snprintf(uid_file, sizeof(uid_file),
               "%s/gpiochip%u/device/firmware_node/uid", GPIO_BASE_PATH,
               *offset);
      if (ReadFileInt(uid_file, &uid_value) < 0)
        continue;
      if (expected_uid == uid_value) {
        match++;
        break;
      }
    }
  }

  closedir(dir);
  return (1 == match);
}
Esempio n. 8
0
/* Write the CMOS reboot field in NVRAM.
 *
 * Sets (value=0) or clears (value!=0) the mask in the byte.
 *
 * Returns 0 if success, or -1 if error. */
static int VbSetCmosRebootField(uint8_t mask, int value) {
  unsigned chnv;
  uint8_t nvbyte;

  /* Get the byte offset from CHNV */
  if (ReadFileInt(ACPI_CHNV_PATH, &chnv) < 0)
    return -1;

  if (0 != VbCmosRead(chnv, 1, &nvbyte))
    return -1;

  /* Set/clear the mask */
  if (value)
    nvbyte |= mask;
  else
    nvbyte &= ~mask;

  /* Write the byte back */
  if (0 != VbCmosWrite(chnv, 1, &nvbyte))
    return -1;

  /* Success */
  return 0;
}
Esempio n. 9
0
int VbGetArchPropertyInt(const char* name) {
  int value = -1;

  /* Values from ACPI */
  if (!strcasecmp(name,"fmap_base")) {
    unsigned fmap_base;
    if (ReadFileInt(ACPI_FMAP_PATH, &fmap_base) < 0)
      return -1;
    else
      value = (int)fmap_base;
  }

  /* Switch positions */
  if (!strcasecmp(name,"devsw_cur")) {
    /* Systems with virtual developer switches return at-boot value */
    int flags = VbGetSystemPropertyInt("vdat_flags");
    if ((flags != -1) && (flags & VBSD_HONOR_VIRT_DEV_SWITCH))
      value = VbGetSystemPropertyInt("devsw_boot");
    else
      value = ReadGpio(GPIO_SIGNAL_TYPE_DEV);
  } else if (!strcasecmp(name,"recoverysw_cur")) {
    value = ReadGpio(GPIO_SIGNAL_TYPE_RECOVERY);
  } else if (!strcasecmp(name,"wpsw_cur")) {
    value = ReadGpio(GPIO_SIGNAL_TYPE_WP);
    if (-1 != value && FwidStartsWith("Mario."))
      value = 1 - value;  /* Mario reports this backwards */
  } else if (!strcasecmp(name,"recoverysw_ec_boot")) {
    value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_EC_BOOT);
  }

  /* Fields for old systems which don't have VbSharedData */
  if (VbSharedDataVersion() < 2) {
    if (!strcasecmp(name,"recovery_reason")) {
      value = VbGetRecoveryReason();
    } else if (!strcasecmp(name,"devsw_boot")) {
      value = ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT);
    } else if (!strcasecmp(name,"recoverysw_boot")) {
      value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_BOOT);
    } else if (!strcasecmp(name,"wpsw_boot")) {
      value = ReadFileBit(ACPI_CHSW_PATH, CHSW_WP_BOOT);
      if (-1 != value && FwidStartsWith("Mario."))
        value = 1 - value;  /* Mario reports this backwards */
    }
  }

  /* Saved memory is at a fixed location for all H2C BIOS.  If the CHSW
   * path exists in sysfs, it's a H2C BIOS. */
  if (!strcasecmp(name,"savedmem_base")) {
    unsigned savedmem_base;
    if (ReadFileInt(ACPI_CHSW_PATH, &savedmem_base) < 0)
      return -1;
    else
      return 0x00F00000;
  } else if (!strcasecmp(name,"savedmem_size")) {
    unsigned savedmem_size;
    if (ReadFileInt(ACPI_CHSW_PATH, &savedmem_size) < 0)
      return -1;
    else
      return 0x00100000;
  }

  /* NV storage values.  If unable to get from NV storage, fall back to the
   * CMOS reboot field used by older BIOS (e.g. Mario). */
  if (!strcasecmp(name,"recovery_request")) {
    value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
    if (-1 == value)
      value = VbGetCmosRebootField(CMOSRF_RECOVERY);
  } else if (!strcasecmp(name,"dbg_reset")) {
    value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
    if (-1 == value)
      value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET);
  } else if (!strcasecmp(name,"fwb_tries")) {
    value = VbGetNvStorage(VBNV_TRY_B_COUNT);
    if (-1 == value)
      value = VbGetCmosRebootField(CMOSRF_TRY_B);
  }

  /* Firmware update tries is now stored in the kernel field.  On
   * older systems where it's not, it was stored in a file in the
   * stateful partition. */
  if (!strcasecmp(name,"fwupdate_tries")) {
    unsigned fwupdate_value;
    if (-1 != VbGetNvStorage(VBNV_KERNEL_FIELD))
      return -1;  /* NvStorage supported; fail through arch-specific
                   * implementation to normal implementation. */
    /* Read value from file; missing file means value=0. */
    if (ReadFileInt(NEED_FWUPDATE_PATH, &fwupdate_value) < 0)
      value = 0;
    else
      value = (int)fwupdate_value;
  }

  return value;
}
Esempio n. 10
0
/* Read a GPIO of the specified signal type (see ACPI GPIO SignalType).
 *
 * Returns 1 if the signal is asserted, 0 if not asserted, or -1 if error. */
static int ReadGpio(unsigned signal_type) {
  char name[128];
  int index = 0;
  unsigned gpio_type;
  unsigned active_high;
  unsigned controller_num;
  unsigned controller_offset = 0;
  char controller_name[128];
  unsigned value;
  const struct GpioChipset *chipset;

  /* Scan GPIO.* to find a matching signal type */
  for (index = 0; ; index++) {
    snprintf(name, sizeof(name), "%s.%d/GPIO.0", ACPI_GPIO_PATH, index);
    if (ReadFileInt(name, &gpio_type) < 0)
      return -1;                  /* Ran out of GPIOs before finding a match */
    if (gpio_type == signal_type)
      break;
  }

  /* Read attributes and controller info for the GPIO */
  snprintf(name, sizeof(name), "%s.%d/GPIO.1", ACPI_GPIO_PATH, index);
  if (ReadFileInt(name, &active_high) < 0)
    return -1;
  snprintf(name, sizeof(name), "%s.%d/GPIO.2", ACPI_GPIO_PATH, index);
  if (ReadFileInt(name, &controller_num) < 0)
    return -1;
  /* Do not attempt to read GPIO that is set to -1 in ACPI */
  if (controller_num == 0xFFFFFFFF)
    return -1;

  /* Check for chipsets we recognize. */
  snprintf(name, sizeof(name), "%s.%d/GPIO.3", ACPI_GPIO_PATH, index);
  if (!ReadFileString(controller_name, sizeof(controller_name), name))
    return -1;
  chipset = FindChipset(controller_name);
  if (chipset == NULL)
    return -1;

  /* Modify GPIO number by driver's offset */
  if (!chipset->ChipOffsetAndGpioNumber(&controller_num, &controller_offset,
                                        chipset->name))
    return -1;
  controller_offset += controller_num;

  /* Try reading the GPIO value */
  snprintf(name, sizeof(name), "%s/gpio%d/value",
           GPIO_BASE_PATH, controller_offset);
  if (ReadFileInt(name, &value) < 0) {
    /* Try exporting the GPIO */
    FILE* f = fopen(GPIO_EXPORT_PATH, "wt");
    if (!f)
      return -1;
    fprintf(f, "%u", controller_offset);
    fclose(f);

    /* Try re-reading the GPIO value */
    if (ReadFileInt(name, &value) < 0)
      return -1;
  }

  /* Normalize the value read from the kernel in case it is not always 1. */
  value = value ? 1 : 0;

  /* Compare the GPIO value with the active value and return 1 if match. */
  return (value == active_high ? 1 : 0);
}
Esempio n. 11
0
int ReadFileBit(const char* filename, int bitmask) {
  int value = ReadFileInt(filename);
  if (value == -1)
    return -1;
  else return (value & bitmask ? 1 : 0);
}