pkg/nvme: add NVMe package

This adds a NVMe package for performing various low-level operations on
NVMe devices. Only the most important (to us) calls are implemented as
NVMe has a vast API surface.

Change-Id: I532894c3c2eb780309993a1688226c92c91cdedf
Reviewed-on: https://review.monogon.dev/c/monogon/+/999
Reviewed-by: Mateusz Zalega <mateusz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/pkg/nvme/uint128le.go b/metropolis/pkg/nvme/uint128le.go
new file mode 100644
index 0000000..a25adb7
--- /dev/null
+++ b/metropolis/pkg/nvme/uint128le.go
@@ -0,0 +1,29 @@
+package nvme
+
+import (
+	"math"
+	"math/big"
+)
+
+// uint128 little endian composed of two uint64s, readable by binary.Read.
+// Auxiliary type to simplify structures with uint128s (of which NVMe has
+// quite a few).
+type uint128le struct {
+	Lo, Hi uint64
+}
+
+// BigInt returns u as a bigint
+func (u uint128le) BigInt() *big.Int {
+	v := new(big.Int).SetUint64(u.Hi)
+	v = v.Lsh(v, 64)
+	v = v.Or(v, new(big.Int).SetUint64(u.Lo))
+	return v
+}
+
+// Uint64 returns u as a clamped uint64
+func (u uint128le) Uint64() uint64 {
+	if u.Hi > 0 {
+		return math.MaxUint64
+	}
+	return u.Lo
+}