void save_mrc_data(struct pei_data *pei_data) { u16 c1, c2, checksum; /* Save the MRC S3 restore data to cbmem */ store_current_mrc_cache(pei_data->mrc_output, pei_data->mrc_output_len); /* Save the MRC seed values to CMOS */ cmos_write32(CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed); printk(BIOS_DEBUG, "Save scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); cmos_write32(CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3); printk(BIOS_DEBUG, "Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); /* Save a simple checksum of the seed values */ c1 = compute_ip_checksum((u8*)&pei_data->scrambler_seed, sizeof(u32)); c2 = compute_ip_checksum((u8*)&pei_data->scrambler_seed_s3, sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); cmos_write(checksum & 0xff, CMOS_OFFSET_MRC_SEED_CHK); cmos_write((checksum >> 8) & 0xff, CMOS_OFFSET_MRC_SEED_CHK+1); }
static int write_seeds_to_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum; struct udevice *dev; int ret = 0; ret = uclass_get_device(UCLASS_RTC, 0, &dev); if (ret) { debug("Cannot find RTC: err=%d\n", ret); return -ENODEV; } /* Save the MRC seed values to CMOS */ rtc_write32(dev, CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed); debug("Save scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); rtc_write32(dev, CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3); debug("Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); /* Save a simple checksum of the seed values */ c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed, sizeof(u32)); c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3, sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK, checksum & 0xff); rtc_write8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1, (checksum >> 8) & 0xff); return 0; }
static int read_seed_from_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum, seed_checksum; struct udevice *dev; int ret = 0; ret = uclass_get_device(UCLASS_RTC, 0, &dev); if (ret) { debug("Cannot find RTC: err=%d\n", ret); return -ENODEV; } /* * Read scrambler seeds from CMOS RAM. We don't want to store them in * SPI flash since they change on every boot and that would wear down * the flash too much. So we store these in CMOS and the large MRC * data in SPI flash. */ ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed); if (!ret) { ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3, &pei_data->scrambler_seed_s3); } if (ret) { debug("Failed to read from RTC %s\n", dev->name); return ret; } debug("Read scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); /* Compute seed checksum and compare */ c1 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed, sizeof(u32)); c2 = compute_ip_checksum((u8 *)&pei_data->scrambler_seed_s3, sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); seed_checksum = rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK); seed_checksum |= rtc_read8(dev, CMOS_OFFSET_MRC_SEED_CHK + 1) << 8; if (checksum != seed_checksum) { debug("%s: invalid seed checksum\n", __func__); pei_data->scrambler_seed = 0; pei_data->scrambler_seed_s3 = 0; return -EINVAL; } return 0; }
void save_mrc_data(struct pei_data *pei_data) { u16 c1, c2, checksum; struct mrc_data_container *mrcdata; int output_len = ALIGN(pei_data->mrc_output_len, 16); /* Save the MRC S3 restore data to cbmem */ mrcdata = cbmem_add (CBMEM_ID_MRCDATA, output_len + sizeof(struct mrc_data_container)); if (mrcdata != NULL) { printk(BIOS_DEBUG, "Relocate MRC DATA from %p to %p (%u bytes)\n", pei_data->mrc_output, mrcdata, output_len); mrcdata->mrc_signature = MRC_DATA_SIGNATURE; mrcdata->mrc_data_size = output_len; mrcdata->reserved = 0; memcpy(mrcdata->mrc_data, pei_data->mrc_output, pei_data->mrc_output_len); /* Zero the unused space in aligned buffer. */ if (output_len > pei_data->mrc_output_len) memset(mrcdata->mrc_data+pei_data->mrc_output_len, 0, output_len - pei_data->mrc_output_len); mrcdata->mrc_checksum = compute_ip_checksum(mrcdata->mrc_data, mrcdata->mrc_data_size); } /* Save the MRC seed values to CMOS */ cmos_write32(CMOS_OFFSET_MRC_SEED, pei_data->scrambler_seed); printk(BIOS_DEBUG, "Save scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); cmos_write32(CMOS_OFFSET_MRC_SEED_S3, pei_data->scrambler_seed_s3); printk(BIOS_DEBUG, "Save s3 scrambler seed 0x%08x to CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); /* Save a simple checksum of the seed values */ c1 = compute_ip_checksum((u8*)&pei_data->scrambler_seed, sizeof(u32)); c2 = compute_ip_checksum((u8*)&pei_data->scrambler_seed_s3, sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); cmos_write(checksum & 0xff, CMOS_OFFSET_MRC_SEED_CHK); cmos_write((checksum >> 8) & 0xff, CMOS_OFFSET_MRC_SEED_CHK+1); }
static void prepare_mrc_cache(struct pei_data *pei_data) { struct mrc_data_container *mrc_cache; u16 c1, c2, checksum, seed_checksum; // preset just in case there is an error pei_data->mrc_input = NULL; pei_data->mrc_input_len = 0; /* Read scrambler seeds from CMOS */ pei_data->scrambler_seed = cmos_read32(CMOS_OFFSET_MRC_SEED); printk(BIOS_DEBUG, "Read scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); pei_data->scrambler_seed_s3 = cmos_read32(CMOS_OFFSET_MRC_SEED_S3); printk(BIOS_DEBUG, "Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); /* Compute seed checksum and compare */ c1 = compute_ip_checksum((u8*)&pei_data->scrambler_seed, sizeof(u32)); c2 = compute_ip_checksum((u8*)&pei_data->scrambler_seed_s3, sizeof(u32)); checksum = add_ip_checksums(sizeof(u32), c1, c2); seed_checksum = cmos_read(CMOS_OFFSET_MRC_SEED_CHK); seed_checksum |= cmos_read(CMOS_OFFSET_MRC_SEED_CHK+1) << 8; if (checksum != seed_checksum) { printk(BIOS_ERR, "%s: invalid seed checksum\n", __func__); pei_data->scrambler_seed = 0; pei_data->scrambler_seed_s3 = 0; return; } if ((mrc_cache = find_current_mrc_cache()) == NULL) { /* error message printed in find_current_mrc_cache */ return; } pei_data->mrc_input = mrc_cache->mrc_data; pei_data->mrc_input_len = mrc_cache->mrc_data_size; printk(BIOS_DEBUG, "%s: at %p, size %x checksum %04x\n", __func__, pei_data->mrc_input, pei_data->mrc_input_len, mrc_cache->mrc_checksum); }