Пример #1
0
int envy_bios_parse_power_budget(struct envy_bios *bios) {
	struct envy_bios_power_budget *budget = &bios->power.budget;
	int i, err = 0;

	if (!budget->offset)
		return -EINVAL;

	bios_u8(bios, budget->offset + 0x0, &budget->version);
	switch(budget->version) {
	case 0x10:
	case 0x20:
	case 0x30:
		err |= bios_u8(bios, budget->offset + 0x1, &budget->hlen);
		err |= bios_u8(bios, budget->offset + 0x2, &budget->rlen);
		err |= bios_u8(bios, budget->offset + 0x3, &budget->entriesnum);
		budget->valid = !err;
		break;
	default:
		ENVY_BIOS_ERR("Unknown POWER BUDGET table version 0x%x\n", budget->version);
		return -EINVAL;
	};

	err = 0;
	budget->entries = malloc(budget->entriesnum * sizeof(struct envy_bios_power_budget_entry));
	memset(budget->entries, 0x0, budget->entriesnum * sizeof(struct envy_bios_power_budget_entry));
	for (i = 0; i < budget->entriesnum; i++) {
		uint16_t data = budget->offset + budget->hlen + i * budget->rlen;

		budget->entries[i].offset = data;

		if (budget->rlen == 0x6) {
			err |= bios_u32(bios, data + 0x02, &budget->entries[i].avg);
		} else {
			err |= bios_u32(bios, data + 0x02, &budget->entries[i].min);
			err |= bios_u32(bios, data + 0x06, &budget->entries[i].avg);
			err |= bios_u32(bios, data + 0x0a, &budget->entries[i].peak);
			err |= bios_u32(bios, data + 0x12, &budget->entries[i].unkn12);
		}

		budget->entries[i].valid = !err;
	}

	return 0;
}
Пример #2
0
int envy_bios_parse_power_fan(struct envy_bios *bios) {
	struct envy_bios_power_fan *fan = &bios->power.fan;
	uint16_t data;
	int err = 0;

	if (!fan->offset)
		return -EINVAL;

	bios_u8(bios, fan->offset + 0x0, &fan->version);
	switch(fan->version) {
	case 0x10:
		err |= bios_u8(bios, fan->offset + 0x1, &fan->hlen);
		err |= bios_u8(bios, fan->offset + 0x2, &fan->rlen);
		err |= bios_u8(bios, fan->offset + 0x3, &fan->entriesnum);

		fan->valid = !err;
		break;
	default:
		ENVY_BIOS_ERR("Unknown FAN table version 0x%x\n", fan->version);
		return -EINVAL;
	};

	/* go to the first entry */
	data = fan->offset + fan->hlen;

	bios_u8(bios, data + 0x00, &fan->type);
	bios_u8(bios, data + 0x02, &fan->duty_min);
	bios_u8(bios, data + 0x03, &fan->duty_max);
	/* 0x10 == constant to 9? */
	bios_u32(bios, data + 0x0b, &fan->divisor); fan->divisor &= 0xffffff;
	bios_u16(bios, data + 0x0e, &fan->unk0e); /* looks like the fan bump delay */
	bios_u16(bios, data + 0x10, &fan->unk10); /* looks like the fan slow down delay */
	bios_u16(bios, data + 0x14, &fan->unboost_unboost_ms);
	bios_u8(bios, data + 0x17, &fan->duty_boosted); /* threshold = 96 °C */

	/* temp fan bump min = 45°C */
	/* temp fan max = 95°C */

	return 0;
}
Пример #3
0
static void print_nv01_init_script(struct envy_bios *bios, FILE *out, unsigned offset, unsigned mask) {
	unsigned len;
	uint8_t op;
	uint8_t arg8_0, arg8_1, arg8_2;
	uint16_t arg16_0;
	uint32_t arg32_0, arg32_1, arg32_2;
	int err = 0;
	if (!(mask & ENVY_BIOS_PRINT_SCRIPTS))
		return;
	fprintf(out, "Init script at 0x%x:\n", offset);
	while (1) {
		if (bios_u8(bios, offset, &op)) {
			ENVY_BIOS_ERR("Init script out of bounds!\n");
			return;
		}
		switch (op) {
		case 0x6e:	/* NV01+ */
			len = 13;
			err |= bios_u32(bios, offset+1, &arg32_0);
			err |= bios_u32(bios, offset+5, &arg32_1);
			err |= bios_u32(bios, offset+9, &arg32_2);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tMMIO_MASK 0x%06x &= 0x%08x |= 0x%08x\n", arg32_0, arg32_1, arg32_2);
			break;
		case 0x7a:	/* NV03+ */
			len = 9;
			err |= bios_u32(bios, offset+1, &arg32_0);
			err |= bios_u32(bios, offset+5, &arg32_1);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tMMIO_WR 0x%06x <= 0x%08x\n", arg32_0, arg32_1);
			break;
		case 0x77:	/* NV03+ */
			len = 7;
			err |= bios_u32(bios, offset+1, &arg32_0);
			err |= bios_u16(bios, offset+5, &arg16_0);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tMMIO_WR16 0x%06x <= 0x%04x\n", arg32_0, arg16_0);
			break;
		case 0x79:	/* NV03+ */
			len = 13;
			err |= bios_u32(bios, offset+1, &arg32_0);
			err |= bios_u32(bios, offset+5, &arg32_1);
			err |= bios_u32(bios, offset+9, &arg32_2);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tMMIO_WR_CRYSTAL 0x%06x <= 0x%08x / 0x%08x\n", arg32_0, arg32_1, arg32_2);
			break;
		case 0x74:	/* NV03+ */
			len = 3;
			err |= bios_u16(bios, offset+1, &arg16_0);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tUSLEEP %d\n", arg16_0);
			break;
		case 0x69:	/* NV03+ */
			len = 5;
			err |= bios_u16(bios, offset+1, &arg16_0);
			err |= bios_u8(bios, offset+3, &arg8_0);
			err |= bios_u8(bios, offset+4, &arg8_1);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tIO_MASK 0x%04x &= 0x%02x |= 0x%02x\n", arg16_0, arg8_0, arg8_1);
			break;
		case 0x78:	/* NV03+ */
			len = 6;
			err |= bios_u16(bios, offset+1, &arg16_0);
			err |= bios_u8(bios, offset+3, &arg8_0);
			err |= bios_u8(bios, offset+4, &arg8_1);
			err |= bios_u8(bios, offset+5, &arg8_2);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tIOIDX_MASK 0x%04x[0x%02x] &= 0x%02x |= 0x%02x\n", arg16_0, arg8_0, arg8_1, arg8_2);
			break;
		case 0x6d:	/* NV03+ */
			len = 2;
			err |= bios_u8(bios, offset+1, &arg8_0);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tIF_MEM_SIZE 0x%02x\n", arg8_0);
			break;
		case 0x73:	/* NV03+ */
			len = 9;
			err |= bios_u32(bios, offset+1, &arg32_0);
			err |= bios_u32(bios, offset+5, &arg32_1);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tIF_STRAPS & 0x%08x == 0x%08x\n", arg32_0, arg32_1);
			break;
		case 0x72:	/* NV03+ */
			len = 1;
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tRESUME\n");
			break;
		case 0x63:	/* NV03+ */
			len = 1;
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tCOMPUTE_MEM\n");
			break;
		case 0x71:	/* NV01+ */
			len = 1;
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tQUIT\n");
			fprintf(out, "\n");
			return;
		case 0x70:	/* NV01:NV03 */
			len = 7;
			err |= bios_u16(bios, offset+1, &arg16_0);
			err |= bios_u32(bios, offset+3, &arg32_0);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tDAC_PLL 0x%04x <= 0x%08x\n", arg16_0, arg32_0);
			break;
		case 0x64:	/* NV01:NV03 */
			len = 5;
			err |= bios_u16(bios, offset+1, &arg16_0);
			err |= bios_u8(bios, offset+3, &arg8_0);
			err |= bios_u8(bios, offset+4, &arg8_1);
			if (err) {
				ENVY_BIOS_ERR("Init script out of bounds!\n");
				return;
			}
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tDAC_MASK 0x%04x &= 0x%02x |= 0x%02x\n", arg16_0, arg8_0, arg8_1);
			break;
		case 0xff:	/* NV01:NV03 */
			len = 1;
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\tQUIT\n");
			fprintf(out, "\n");
			return;
		default:
			len = 1;
			dump_hex_script(bios, out, offset, len);
			fprintf(out, "\n");
			ENVY_BIOS_ERR("Unknown op 0x%02x in init script!\n", op);
			return;
		}
		offset += len;
	}
}
Пример #4
0
void
envy_bios_print_mem_train_ptrn(struct envy_bios *bios, FILE *out, unsigned mask) {
	struct envy_bios_mem_train_ptrn *mtp = &bios->mem.train_ptrn;
	int i, j;
	uint32_t data, idx;
	uint16_t data_off;
	uint8_t bits;

	if (!mtp->offset || !(mask & ENVY_BIOS_PRINT_MEM))
		return;

	fprintf(out, "MEM TRAIN PATTERN table at 0x%x, version %x\n", mtp->offset, mtp->version);
	envy_bios_dump_hex(bios, out, mtp->offset, mtp->hlen, mask);
	if (mask & ENVY_BIOS_PRINT_VERBOSE) fprintf(out, "\n");

	for (i = 0; i < mtp->entriesnum; i++) {
		data_off = mtp->entries[i].offset;
		bits = mtp->entries[i].bits;
		fprintf(out, "Set %2i: %u bits, modulo %u", i, mtp->entries[i].bits, mtp->entries[i].modulo);
		if (mtp->entries[i].indirect) {
			data_off = mtp->entries[mtp->entries[i].indirect_entry].offset;
			bits = mtp->entries[mtp->entries[i].indirect_entry].bits;
			fprintf(out, ". indirect(%2d)\n", mtp->entries[i].indirect_entry);
		} else {
			data_off = mtp->entries[i].offset;
			bits = mtp->entries[i].bits;
			fprintf(out, ". direct(%2d)\n", mtp->entries[i].indirect_entry);
		}
		envy_bios_dump_hex(bios, out, mtp->entries[i].offset, mtp->rlen, mask);
		if (mask & ENVY_BIOS_PRINT_VERBOSE) fprintf(out, "\n");

		for (j = 0; j < mtp->entries[i].modulo; j++) {
			uint32_t p_bits;
			uint32_t mask;
			uint16_t off;
			uint8_t  mod;

			if (mtp->entries[i].indirect) {
				p_bits = j * mtp->entries[i].bits;
				mask = (1ULL << mtp->entries[i].bits) - 1;
				off = p_bits / 8;
				mod = p_bits % 8;

				bios_u32(bios, mtp->entries[i].offset + mtp->rlen + off, &idx);
				idx = idx >> mod;
				idx = idx & mask;
			} else {
				idx = j;
			}

			p_bits = idx * bits;
			mask = (1ULL << bits) - 1;
			off = p_bits / 8;
			mod = p_bits % 8;

			bios_u32(bios, data_off + mtp->rlen + off, &data);
			data = data >> mod;
			data = data & mask;

			fprintf(out, "  %2u: [%08x]\n", idx, data);
		}