diff --git a/Makefile.am b/Makefile.am
index f850a29..f5e7ded 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -191,7 +191,7 @@ libpdbg_la_SOURCES = \
 	libpdbg/xbus.c
 
 libpdbg_la_CFLAGS = -Wall -Werror
-libpdbg_la_LIBADD = libcronus.la
+libpdbg_la_LIBADD = libcronus.la libsbefifo.la
 
 if BUILD_LIBFDT
 libpdbg_la_CFLAGS += -I$(top_srcdir)/libfdt
diff --git a/libpdbg/hwunit.h b/libpdbg/hwunit.h
index 501ec74..37c7661 100644
--- a/libpdbg/hwunit.h
+++ b/libpdbg/hwunit.h
@@ -75,10 +75,7 @@ struct sbefifo {
 	int (*thread_step)(struct sbefifo *, uint32_t core_id, uint32_t thread_id);
 	int (*thread_sreset)(struct sbefifo *, uint32_t core_id, uint32_t thread_id);
 	uint32_t (*ffdc_get)(struct sbefifo *, const uint8_t **, uint32_t *);
-	int fd;
-	uint32_t status;
-	uint8_t *ffdc;
-	uint32_t ffdc_len;
+	struct sbefifo_context *sf_ctx;
 };
 #define target_to_sbefifo(x) container_of(x, struct sbefifo, target)
 
diff --git a/libpdbg/sbefifo.c b/libpdbg/sbefifo.c
index 92f8220..249f115 100644
--- a/libpdbg/sbefifo.c
+++ b/libpdbg/sbefifo.c
@@ -20,228 +20,22 @@
 #include <inttypes.h>
 #include <fcntl.h>
 
+#include <libsbefifo/libsbefifo.h>
+
 #include "hwunit.h"
 #include "debug.h"
 
-#define SBEFIFO_CMD_CLASS_CONTROL        0xA100
-#define   SBEFIFO_CMD_EXECUTE_ISTEP      0x0001
-
-#define SBEFIFO_CMD_CLASS_MEMORY         0xA400
-#define   SBEFIFO_CMD_GET_MEMORY         0x0001
-#define   SBEFIFO_CMD_PUT_MEMORY         0x0002
-
-#define SBEFIFO_CMD_CLASS_INSTRUCTION    0xA700
-#define   SBEFIFO_CMD_CONTROL_INSN       0x0001
-
-#define SBEFIFO_MEMORY_FLAG_PROC         0x0001
-#define SBEFIFO_MEMORY_FLAG_PBA          0x0002
-#define SBEFIFO_MEMORY_FLAG_AUTO_INCR    0x0004
-#define SBEFIFO_MEMORY_FLAG_ECC_REQ      0x0008
-#define SBEFIFO_MEMORY_FLAG_TAG_REQ      0x0010
-#define SBEFIFO_MEMORY_FLAG_FAST_MODE    0x0020
-#define SBEFIFO_MEMORY_FLAG_LCO_MODE     0x0040 // only for putmem
-#define SBEFIFO_MEMORY_FLAG_CI           0x0080
-#define SBEFIFO_MEMORY_FLAG_PASSTHRU     0x0100
-#define SBEFIFO_MEMORY_FLAG_CACHEINJECT  0x0200 // only for putmem
-
-#define SBEFIFO_INSN_OP_START            0x0
-#define SBEFIFO_INSN_OP_STOP             0x1
-#define SBEFIFO_INSN_OP_STEP             0x2
-#define SBEFIFO_INSN_OP_SRESET           0x3
-
-static void sbefifo_op_dump(const char *prefix, uint8_t *buf, size_t buflen)
-{
-	int i;
-
-	if (!prefix)
-		prefix = "";
-
-	for (i=0; i<buflen/4; i++) {
-		PR_ERROR("   %s 0x%02x%02x%02x%02x\n", prefix,
-			 buf[i*4], buf[i*4+1], buf[i*4+2], buf[i*4+3]);
-	}
-}
-
-static int sbefifo_op_read(struct sbefifo *sbefifo, void *buf, size_t *buflen)
+static uint32_t sbefifo_op_ffdc_get(struct sbefifo *sbefifo, const uint8_t **ffdc, uint32_t *ffdc_len)
 {
-	ssize_t n;
-
-	assert(*buflen > 0);
-
-	n = read(sbefifo->fd, buf, *buflen);
-	if (n < 0) {
-		PR_ERROR("sbefifo: Failed to read, errno=%d\n", errno);
-		return -1;
-	}
-	*buflen = n;
-
-	return 0;
-}
-
-static int sbefifo_op_write(struct sbefifo *sbefifo, void *buf, size_t buflen)
-{
-	ssize_t n;
-
-	n = write(sbefifo->fd, buf, buflen);
-	if (n < 0) {
-		PR_ERROR("sbefifo: Failed to write, errno=%d\n", errno);
-		return -1;
-	}
-	if (n != buflen) {
-		PR_ERROR("sbefifo: Short write %zi of %zi bytes\n", n, buflen);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void sbefifo_ffdc_clear(struct sbefifo *sbefifo)
-{
-	sbefifo->status = 0;
-	if (sbefifo->ffdc) {
-		free(sbefifo->ffdc);
-		sbefifo->ffdc = NULL;
-		sbefifo->ffdc_len = 0;
-	}
-}
-
-static void sbefifo_ffdc_set(struct sbefifo *sbefifo, uint8_t *buf, uint32_t buflen, uint32_t status)
-{
-	sbefifo->status = status;
-
-	sbefifo->ffdc = malloc(buflen);
-	if (!sbefifo->ffdc) {
-		PR_ERROR("sbefifo: Failed to store FFDC data\n");
-		return;
-	}
-
-	memcpy(sbefifo->ffdc, buf, buflen);
-	sbefifo->ffdc_len = buflen;
-}
-
-static uint32_t sbefifo_ffdc_get(struct sbefifo *sbefifo, const uint8_t **ffdc, uint32_t *ffdc_len)
-{
-	*ffdc = sbefifo->ffdc;
-	*ffdc_len = sbefifo->ffdc_len;
-
-	return sbefifo->status;
-}
-
-static int sbefifo_op(struct sbefifo *sbefifo,
-		      uint32_t *msg, uint32_t msg_len, uint16_t cmd,
-		      uint8_t **out, uint32_t *out_len, uint32_t *status)
-{
-	uint8_t *buf;
-	uint32_t resp[2];
-	size_t buflen;
-	uint32_t word_offset, offset;
-	uint16_t value;
-	int rc;
-
-	sbefifo_ffdc_clear(sbefifo);
-
-	assert(msg_len > 0);
-
-	/*
-	 * Allocate extra memory for FFDC (SBEFIFO_MAX_FFDC_SIZE = 0x2000)
-	 * Use *out_len as a hint to expected reply length
-	 */
-	buflen = (*out_len + 0x2000 + 3) & (uint32_t)~3;
-	buf = malloc(buflen);
-	assert(buf);
-
-	rc = sbefifo_op_write(sbefifo, msg, msg_len);
-	if (rc)
-		goto fail;
-
-	rc = sbefifo_op_read(sbefifo, buf, &buflen);
-	if (rc)
-		goto fail;
-
-	/*
-	 * At least 3 words are expected in the response
-	 * header word, status word, header offset word
-	 */
-	if (buflen < 3 * 4) {
-		PR_ERROR("sbefifo: Short read, got %zu\n", buflen);
-		sbefifo_op_dump("DATA:", buf, buflen);
-		goto fail;
-	}
-
-	word_offset = be32toh(*(uint32_t *)(buf + buflen - 4));
-	PR_INFO("sbefifo: status header word offset = %u\n", word_offset);
-
-	offset = buflen - (word_offset * 4);
-	*out_len = offset;
-
-	resp[0] = be32toh(*(uint32_t *)(buf + offset));
-	offset += 4;
-
-	resp[1] = be32toh(*(uint32_t *)(buf + offset));
-	offset += 4;
-
-	PR_INFO("sbefifo: response %08x %08x\n", resp[0], resp[1]);
-
-	value = resp[0] >> 16;
-	if (value != 0xc0de) {
-		PR_ERROR("sbefifo: Expected magic 0xc0de, got 0x%04x\n", value);
-		goto fail;
-	}
-
-	value = resp[0] & 0xffff;
-	if (value != cmd) {
-		PR_ERROR("sbefifo: Expected command 0x%04x, got 0x%04x\n", cmd, value);
-		goto fail;
-	}
-
-	*status = resp[1];
-	if (resp[1] != 0) {
-		PR_ERROR("sbefifo: Operation failed, response=0x%08x\n", resp[1]);
-		sbefifo_ffdc_set(sbefifo, buf + offset, buflen - offset - 4, resp[1]);
-		free(buf);
-		return 1;
-	}
-
-	if (*out_len > 0) {
-		*out = malloc(*out_len);
-		assert(*out);
-
-		memcpy(*out, buf, *out_len);
-	} else {
-		*out = NULL;
-	}
-
-	free(buf);
-	return 0;
-
-fail:
-	free(buf);
-	return -1;
+	return sbefifo_ffdc_get(sbefifo->sf_ctx, ffdc, ffdc_len);
 }
 
 static int sbefifo_op_istep(struct sbefifo *sbefifo,
 			    uint32_t major, uint32_t minor)
 {
-	uint8_t *out;
-	uint32_t msg[3];
-	uint32_t cmd, step, out_len, status;
-	int rc;
-
 	PR_NOTICE("sbefifo: istep %u.%u\n", major, minor);
 
-	cmd = SBEFIFO_CMD_CLASS_CONTROL | SBEFIFO_CMD_EXECUTE_ISTEP;
-	step = (major & 0xff) << 16 | (minor & 0xff);
-
-	msg[0] = htobe32(3);	// number of words
-	msg[1] = htobe32(cmd);
-	msg[2] = htobe32(step);
-
-	out_len = 0;
-	rc = sbefifo_op(sbefifo, msg, sizeof(msg), cmd, &out, &out_len, &status);
-	if (rc)
-		return rc;
-
-	return 0;
+	return sbefifo_istep_execute(sbefifo->sf_ctx, major & 0xff, minor & 0xff);
 }
 
 static int sbefifo_op_getmem(struct sbefifo *sbefifo,
@@ -250,9 +44,8 @@ static int sbefifo_op_getmem(struct sbefifo *sbefifo,
 {
 	uint8_t *out;
 	uint64_t start_addr, end_addr;
-	uint32_t align, offset, len, out_len, status;
-	uint32_t msg[6];
-	uint32_t cmd, flags;
+	uint32_t align, offset, len;
+	uint16_t flags;
 	int rc;
 
 	align = ci ? 8 : 128;
@@ -271,33 +64,18 @@ static int sbefifo_op_getmem(struct sbefifo *sbefifo,
 	PR_NOTICE("sbefifo: getmem addr=0x%016" PRIx64 ", len=%u\n",
 		  start_addr, len);
 
-	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_GET_MEMORY;
 	if (ci)
 		flags = SBEFIFO_MEMORY_FLAG_PROC | SBEFIFO_MEMORY_FLAG_CI;
 	else
 		flags = SBEFIFO_MEMORY_FLAG_PBA;
 
-	msg[0] = htobe32(6);	// number of words
-	msg[1] = htobe32(cmd);
-	msg[2] = htobe32(flags);
-	msg[3] = htobe32(start_addr >> 32);
-	msg[4] = htobe32(start_addr & 0xffffffff);
-	msg[5] = htobe32(len);
+	rc = sbefifo_mem_get(sbefifo->sf_ctx, start_addr, len, flags, &out);
+
+	pdbg_progress_tick(len, len);
 
-	out_len = len + 4;
-	rc = sbefifo_op(sbefifo, msg, sizeof(msg), cmd, &out, &out_len, &status);
 	if (rc)
 		return rc;
 
-	pdbg_progress_tick(len + 4, out_len);
-
-	if (out_len != size + 4) {
-		PR_ERROR("sbefifo: getmem error got %u, expected %"PRIu64"\n", out_len, size + 4);
-		if (out_len > 0)
-			free(out);
-		return -1;
-	}
-
 	memcpy(data, out+offset, size);
 	free(out);
 
@@ -308,10 +86,8 @@ static int sbefifo_op_putmem(struct sbefifo *sbefifo,
 			     uint64_t addr, uint8_t *data, uint64_t size,
 			     bool ci)
 {
-	uint8_t *out;
-	uint32_t *msg;
-	uint32_t align, len, msg_len, out_len, status;
-	uint32_t cmd, flags, count;
+	uint32_t align, len;
+	uint16_t flags;
 	int rc;
 
 	align = ci ? 8 : 128;
@@ -332,59 +108,26 @@ static int sbefifo_op_putmem(struct sbefifo *sbefifo,
 	}
 
 	len = size & 0xffffffff;
-	msg_len = 6 * 4 + len;
-	msg = (uint32_t *)malloc(msg_len);
-	assert(msg);
 
 	PR_NOTICE("sbefifo: putmem addr=0x%016"PRIx64", len=%u\n", addr, len);
 
-	cmd = SBEFIFO_CMD_CLASS_MEMORY | SBEFIFO_CMD_PUT_MEMORY;
 	if (ci)
 		flags = SBEFIFO_MEMORY_FLAG_PROC | SBEFIFO_MEMORY_FLAG_CI;
 	else
 		flags = SBEFIFO_MEMORY_FLAG_PBA;
 
-	msg[0] = htobe32(msg_len/4);	// number of words
-	msg[1] = htobe32(cmd);
-	msg[2] = htobe32(flags);
-	msg[3] = htobe32(addr >> 32);
-	msg[4] = htobe32(addr & 0xffffffff);
-	msg[5] = htobe32(len);
-	memcpy(&msg[6], data, len);
+	rc = sbefifo_mem_put(sbefifo->sf_ctx, addr, data, len, flags);
 
-	out_len = 4;
-	rc = sbefifo_op(sbefifo, msg, msg_len, cmd, &out, &out_len, &status);
-	if (rc)
-		return rc;
-
-	pdbg_progress_tick(4, out_len);
-
-	if (out_len != 4) {
-		PR_ERROR("sbefifo: putmem error got %u, expected 4\n", out_len);
-		if (out_len > 0)
-			free(out);
-		return -1;
-	}
-
-	count = be32toh(*(uint32_t *)out);
-	free(out);
-
-	if (count != len) {
-		PR_ERROR("sbefifo: putmem wrote %u bytes of %u\n", count, len);
-		return -1;
-	}
+	pdbg_progress_tick(len, len);
 
-	return 0;
+	return rc;
 }
 
 static int sbefifo_op_control(struct sbefifo *sbefifo,
 			      uint32_t core_id, uint32_t thread_id,
 			      uint32_t oper)
 {
-	uint8_t *out;
-	uint32_t msg[3];
-	uint32_t cmd, op, out_len, status, mode = 0;
-	int rc;
+	uint8_t mode = 0;
 
 	/* Enforce special-wakeup for thread stop and sreset */
 	if ((oper & 0xf) == SBEFIFO_INSN_OP_STOP ||
@@ -393,22 +136,7 @@ static int sbefifo_op_control(struct sbefifo *sbefifo,
 
 	PR_NOTICE("sbefifo: control c:0x%x, t:0x%x, op:%u mode:%u\n", core_id, thread_id, oper, mode);
 
-	op = (mode << 16) | ((core_id & 0xff) << 8) | ((thread_id & 0x0f) << 4) | (oper & 0x0f);
-	cmd = SBEFIFO_CMD_CLASS_INSTRUCTION | SBEFIFO_CMD_CONTROL_INSN;
-
-	msg[0] = htobe32(3);	// number of words
-	msg[1] = htobe32(cmd);
-	msg[2] = htobe32(op);
-
-	out_len = 0;
-	rc = sbefifo_op(sbefifo, msg, sizeof(msg), cmd, &out, &out_len, &status);
-	if (rc)
-		return rc;
-
-	if (out_len > 0)
-		free(out);
-
-	return 0;
+	return sbefifo_control_insn(sbefifo->sf_ctx, core_id & 0xff, thread_id & 0xff, oper & 0xff, mode);
 }
 
 static int sbefifo_op_thread_start(struct sbefifo *sbefifo,
@@ -439,14 +167,15 @@ static int sbefifo_probe(struct pdbg_target *target)
 {
 	struct sbefifo *sf = target_to_sbefifo(target);
 	const char *sbefifo_path;
+	int rc;
 
 	sbefifo_path = pdbg_target_property(target, "device-path", NULL);
 	assert(sbefifo_path);
 
-	sf->fd = open(sbefifo_path, O_RDWR | O_SYNC);
-	if (sf->fd < 0) {
+	rc = sbefifo_connect(sbefifo_path, &sf->sf_ctx);
+	if (rc) {
 		PR_ERROR("Unable to open sbefifo driver %s\n", sbefifo_path);
-		return -1;
+		return rc;
 	}
 
 	return 0;
@@ -466,8 +195,7 @@ struct sbefifo kernel_sbefifo = {
 	.thread_stop = sbefifo_op_thread_stop,
 	.thread_step = sbefifo_op_thread_step,
 	.thread_sreset = sbefifo_op_thread_sreset,
-	.ffdc_get = sbefifo_ffdc_get,
-	.fd = -1,
+	.ffdc_get = sbefifo_op_ffdc_get,
 };
 DECLARE_HW_UNIT(kernel_sbefifo);
 
