int serialport_read(unsigned char *buf, unsigned int readcnt) { #if IS_WINDOWS DWORD tmp = 0; #else ssize_t tmp = 0; #endif while (readcnt > 0) { #if IS_WINDOWS ReadFile(sp_fd, buf, readcnt, &tmp, NULL); #else tmp = read(sp_fd, buf, readcnt); #endif if (tmp == -1) { msg_perr("Serial port read error!\n"); return 1; } if (!tmp) msg_pdbg2("Empty read\n"); readcnt -= tmp; buf += tmp; } return 0; }
int serialport_write(const unsigned char *buf, unsigned int writecnt) { #if IS_WINDOWS DWORD tmp = 0; #else ssize_t tmp = 0; #endif unsigned int empty_writes = 250; /* results in a ca. 125ms timeout */ while (writecnt > 0) { #if IS_WINDOWS WriteFile(sp_fd, buf, writecnt, &tmp, NULL); #else tmp = write(sp_fd, buf, writecnt); #endif if (tmp == -1) { msg_perr("Serial port write error!\n"); return 1; } if (!tmp) { msg_pdbg2("Empty write\n"); empty_writes--; internal_delay(500); if (empty_writes == 0) { msg_perr("Serial port is unresponsive!\n"); return 1; } } writecnt -= tmp; buf += tmp; } return 0; }
static void determine_generation(struct pci_dev *dev) { amd_gen = CHIPSET_AMD_UNKNOWN; msg_pdbg2("Trying to determine the generation of the SPI interface... "); if (dev->device_id == 0x438d) { amd_gen = CHIPSET_SB6XX; msg_pdbg("SB6xx detected.\n"); } else if (dev->device_id == 0x439d) { struct pci_dev *smbus_dev = pci_dev_find(0x1002, 0x4385); if (smbus_dev == NULL) return; uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); if (rev >= 0x39 && rev <= 0x3D) { amd_gen = CHIPSET_SB7XX; msg_pdbg("SB7xx/SP5100 detected.\n"); } else if (rev >= 0x40 && rev <= 0x42) { amd_gen = CHIPSET_SB89XX; msg_pdbg("SB8xx/SB9xx/Hudson-1 detected.\n"); } else { msg_pwarn("SB device found but SMBus revision 0x%02x does not match known values.\n" "Assuming SB8xx/SB9xx/Hudson-1. Please send a log to [email protected]\n", rev); amd_gen = CHIPSET_SB89XX; } } else if (dev->device_id == 0x780e) { /* The PCI ID of the LPC bridge doesn't change between Hudson-2/3/4 and Yangtze (Kabini/Temash) * although they use different SPI interfaces. */ #ifdef USE_YANGTZE_HEURISTICS /* This heuristic accesses the SPI interface MMIO BAR at locations beyond those supported by * Hudson in the hope of getting 0xff readback on older chipsets and non-0xff readback on * Yangtze (and newer, compatible chipsets). */ int i; msg_pdbg("Checking for AMD Yangtze (Kabini/Temash) or later... "); for (i = 0x20; i <= 0x4f; i++) { if (mmio_readb(sb600_spibar + i) != 0xff) { amd_gen = CHIPSET_YANGTZE; msg_pdbg("found.\n"); return; } } msg_pdbg("not found. Assuming Hudson.\n"); amd_gen = CHIPSET_HUDSON234; #else struct pci_dev *smbus_dev = pci_dev_find(0x1022, 0x780B); if (smbus_dev == NULL) { msg_pdbg("No SMBus device with ID 1022:780B found.\n"); return; } uint8_t rev = pci_read_byte(smbus_dev, PCI_REVISION_ID); if (rev >= 0x11 && rev <= 0x15) { amd_gen = CHIPSET_HUDSON234; msg_pdbg("Hudson-2/3/4 detected.\n"); } else if (rev >= 0x39 && rev <= 0x3A) { amd_gen = CHIPSET_YANGTZE; msg_pdbg("Yangtze detected.\n"); } else { msg_pwarn("FCH device found but SMBus revision 0x%02x does not match known values.\n" "Please report this to [email protected] and include this log and\n" "the output of lspci -nnvx, thanks!.\n", rev); } #endif } else msg_pwarn("%s: Unknown LPC device %" PRIx16 ":%" PRIx16 ".\n" "Please report this to [email protected] and include this log and\n" "the output of lspci -nnvx, thanks!\n", __func__, dev->vendor_id, dev->device_id); }
/* Tries to find coreboot IDs in the supplied image and compares them to the current IDs. * Returns... * -1 if IDs in the image do not match the IDs embedded in the current firmware, * 0 if the IDs could not be found in the image or if they match correctly. */ int cb_check_image(const uint8_t *image, int size) { const unsigned int *walk; unsigned int mb_part_offset, mb_vendor_offset; const char *mb_part, *mb_vendor; walk = (const unsigned int *)(image + size - 0x10); walk--; if ((*walk) == 0 || ((*walk) & 0x3ff) != 0) { /* Some NVIDIA chipsets store chipset soft straps (IIRC Hypertransport init info etc.) in * flash at exactly the location where coreboot image size, coreboot vendor name pointer and * coreboot board name pointer are usually stored. In this case coreboot uses an alternate * location for the coreboot image data. */ walk = (const unsigned int *)(image + size - 0x80); walk--; } /* * Check if coreboot last image size is 0 or not a multiple of 1k or * bigger than the chip or if the pointers to vendor ID or mainboard ID * are outside the image of if the start of ID strings are nonsensical * (nonprintable and not \0). */ mb_part_offset = *(walk - 1); mb_vendor_offset = *(walk - 2); if ((*walk) == 0 || ((*walk) & 0x3ff) != 0 || (*walk) > size || mb_part_offset > size || mb_vendor_offset > size) { msg_pdbg("Flash image seems to be a legacy BIOS. Disabling coreboot-related checks.\n"); return 0; } mb_part = (const char *)(image + size - mb_part_offset); mb_vendor = (const char *)(image + size - mb_vendor_offset); if (!isprint((unsigned char)*mb_part) || !isprint((unsigned char)*mb_vendor)) { msg_pdbg("Flash image seems to have garbage in the ID location. " "Disabling coreboot-related checks.\n"); return 0; } msg_pdbg("coreboot last image size (not ROM size) is %d bytes.\n", *walk); msg_pdbg("Manufacturer: %s\n", mb_vendor); msg_pdbg("Mainboard ID: %s\n", mb_part); /* If these are not set, the coreboot table was not found. */ if (!cb_vendor || !cb_model) return 0; /* These comparisons are case insensitive to make things a little less user^Werror prone. */ if (!strcasecmp(mb_vendor, cb_vendor) && !strcasecmp(mb_part, cb_model)) { msg_pdbg2("This coreboot image matches this mainboard.\n"); } else { msg_perr("This coreboot image (%s:%s) does not appear to\n" "be correct for the detected mainboard (%s:%s).\n", mb_vendor, mb_part, cb_vendor, cb_model); return -1; } return 0; }