diff --git a/kernel/spec-i2c.c b/kernel/spec-i2c.c
index 9a25aa938be0d9336eac5b7068254998c2d63f91..0303352df5fb179213007386eaea069f896ddaa1 100644
--- a/kernel/spec-i2c.c
+++ b/kernel/spec-i2c.c
@@ -141,32 +141,36 @@ int mi2c_scan(struct fmc_device *fmc)
 	return found;
 }
 
-/* FIXME: this is very inefficient: read several bytes in a row instead */
 int spec_eeprom_read(struct fmc_device *fmc, uint32_t offset,
 		void *buf, size_t size)
 {
-	int i;
+	int ret = size;
 	uint8_t *buf8 = buf;
 	unsigned char c;
 
-	for(i = 0; i < size; i++) {
-		mi2c_start(fmc);
-		if(mi2c_put_byte(fmc, fmc->eeprom_addr << 1) < 0) {
-			mi2c_stop(fmc);
-			return -EIO;
-		}
+	if (offset > SPEC_I2C_EEPROM_SIZE)
+		return -EINVAL;
+	if (offset + size > SPEC_I2C_EEPROM_SIZE)
+		return -EINVAL;
 
-		mi2c_put_byte(fmc, (offset >> 8) & 0xff);
-		mi2c_put_byte(fmc, offset & 0xff);
-		offset++;
+	/* Read it all in a single loop: hardware allows it */
+	mi2c_start(fmc);
+	if(mi2c_put_byte(fmc, fmc->eeprom_addr << 1) < 0) {
 		mi2c_stop(fmc);
-		mi2c_start(fmc);
-		mi2c_put_byte(fmc, (fmc->eeprom_addr << 1) | 1);
-		mi2c_get_byte(fmc, &c, 0);
+		return -EIO;
+	}
+	mi2c_put_byte(fmc, (offset >> 8) & 0xff);
+	mi2c_put_byte(fmc, offset & 0xff);
+	mi2c_stop(fmc);
+	mi2c_start(fmc);
+	mi2c_put_byte(fmc, (fmc->eeprom_addr << 1) | 1);
+	while (size--) {
+		mi2c_get_byte(fmc, &c, size != 0);
 		*buf8++ = c;
-		mi2c_stop(fmc);
+		//printk("read 0x%08x, %4i to go\n", c, size);
 	}
-	return size;
+	mi2c_stop(fmc);
+	return ret;
 }
 
 int spec_eeprom_write(struct fmc_device *fmc, uint32_t offset,