ipmi_sdr_find_sdr_byid(struct ipmi_intf *intf, char *id)
{
	struct sdr_get_rs *header;
	struct sdr_record_list *e;
	int found = 0;
	int idlen;

	if (!id)
		return NULL;

	idlen = strlen(id);

	if (!sdr_list_itr) {
		sdr_list_itr = ipmi_sdr_start(intf, 0);
		if (!sdr_list_itr) {
			lprintf(LOG_ERR, "Unable to open SDR for reading");
			return NULL;
		}
	}

	/* check what we've already read */
	for (e = sdr_list_head; e; e = e->next) {
		switch (e->type) {
		case SDR_RECORD_TYPE_FULL_SENSOR:
			if (!strncmp((const char *)e->record.full->id_string,
				     (const char *)id,
				     __max(e->record.full->id_code & 0x1f, idlen)))
				return e;
			break;
		case SDR_RECORD_TYPE_COMPACT_SENSOR:
			if (!strncmp((const char *)e->record.compact->id_string,
				     (const char *)id,
				     __max(e->record.compact->id_code & 0x1f, idlen)))
				return e;
			break;
		case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
			if (!strncmp((const char *)e->record.eventonly->id_string,
				     (const char *)id,
				     __max(e->record.eventonly->id_code & 0x1f, idlen)))
				return e;
			break;
		case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR:
			if (!strncmp((const char *)e->record.genloc->id_string,
				     (const char *)id,
				     __max(e->record.genloc->id_code & 0x1f, idlen)))
				return e;
			break;
		case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
			if (!strncmp((const char *)e->record.fruloc->id_string,
				     (const char *)id,
				     __max(e->record.fruloc->id_code & 0x1f, idlen)))
				return e;
			break;
		case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
			if (!strncmp((const char *)e->record.mcloc->id_string,
				     (const char *)id,
				     __max(e->record.mcloc->id_code & 0x1f, idlen)))
				return e;
			break;
		}
	}

	/* now keep looking */
	while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr))) {
		uint8_t *rec;
		struct sdr_record_list *sdrr;

		sdrr = malloc(sizeof (struct sdr_record_list));
		if (!sdrr) {
			lprintf(LOG_ERR, "ipmitool: malloc failure");
			break;
		}
		memset(sdrr, 0, sizeof (struct sdr_record_list));
		sdrr->id = header->id;
		sdrr->type = header->type;

		rec = ipmi_sdr_get_record(intf, header, sdr_list_itr);
		if (!rec) {
			if (sdrr) {
				free(sdrr);
				sdrr = NULL;
			}
			continue;
		}

		switch (header->type) {
		case SDR_RECORD_TYPE_FULL_SENSOR:
			sdrr->record.full =
			    (struct sdr_record_full_sensor *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.full->id_string,
			    (const char *)id,
			    __max(sdrr->record.full->id_code & 0x1f, idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_COMPACT_SENSOR:
			sdrr->record.compact =
			    (struct sdr_record_compact_sensor *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.compact->id_string,
			    (const char *)id,
			    __max(sdrr->record.compact->id_code & 0x1f,
				   idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
			sdrr->record.eventonly =
			    (struct sdr_record_eventonly_sensor *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.eventonly->id_string,
			    (const char *)id,
			    __max(sdrr->record.eventonly->id_code & 0x1f,
				   idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR:
			sdrr->record.genloc =
			    (struct sdr_record_generic_locator *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.genloc->id_string,
			    (const char *)id,
			    __max(sdrr->record.genloc->id_code & 0x1f, idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR:
			sdrr->record.fruloc =
			    (struct sdr_record_fru_locator *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.fruloc->id_string,
			    (const char *)id,
			    __max(sdrr->record.fruloc->id_code & 0x1f, idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
			sdrr->record.mcloc =
			    (struct sdr_record_mc_locator *) rec;
			if (!strncmp(
			    (const char *)sdrr->record.mcloc->id_string,
			    (const char *)id,
			    __max(sdrr->record.mcloc->id_code & 0x1f, idlen)))
				found = 1;
			break;
		case SDR_RECORD_TYPE_ENTITY_ASSOC:
			sdrr->record.entassoc =
			    (struct sdr_record_entity_assoc *) rec;
			break;
		default:
			free(rec);
			rec = NULL;
			if (sdrr) {
				free(sdrr);
				sdrr = NULL;
			}
			continue;
		}

		/* add to global record liset */
		if (!sdr_list_head)
			sdr_list_head = sdrr;
		else
			sdr_list_tail->next = sdrr;

		sdr_list_tail = sdrr;

		if (found)
			return sdrr;
	}

	return NULL;
}