diff --git a/uart/bom/Makefile b/uart/bom/Makefile
new file mode 100644
index 0000000..ebbeb62
--- /dev/null
+++ b/uart/bom/Makefile
@@ -0,0 +1,45 @@
+BOOM=PATH=/home/moko/svn.openmoko.org/trunk/eda/boom:../boom:$$PATH boom
+
+BOOM2=../../../eda-tools/boom
+BOOM_CONFIG=$(BOOM2)/boom-config
+
+KITS=1
+
+EQU=uart.equ dk/digi-key.equ $(shell $(BOOM_CONFIG) equ)
+INV=uart.inv dk/digi-key.inv $(shell $(BOOM_CONFIG) inv)
+DSC=dk/digi-key.dsc $(shell $(BOOM_CONFIG) dsc)
+CHR=$(shell $(BOOM_CONFIG) chr)
+
+
+.PHONY: all again spotless
+.PRECIOUS: %.par %.lst
+
+all: uart.ord
+
+again:
+ $(MAKE) spotless
+ $(MAKE) all
+
+%.ord: %.par $(INV) $(EQU)
+ $(BOOM) part2order $(KITS) $^ >$@ || { rm -f $@; exit 1; }
+
+%.par: $(EQU) $(INV) $(CHR) %.lst uart.sub
+ $(BOOM) bom2part $^ >$@ || { rm -f $@; exit 1; }
+
+dk/digi-key.inv:
+ $(MAKE) -C dk digi-key.inv
+
+dk/digi-key.dsc:
+ $(MAKE) -C dk digi-key.dsc
+
+%.lst: ../*.sch ../*.cmp
+ eeschema --bom `pwd`/../$*.sch
+ mv ../$*.lst .
+
+show-%: %.ord $(DSC)
+ grep -vw UART $< | $(BOOM) prettyord -t - $(DSC) | \
+ sed 's/^... //'
+
+spotless:
+ $(MAKE) -C dk spotless
+ rm -f uart.lst uart.par uart.ord
diff --git a/uart/bom/dk/Makefile b/uart/bom/dk/Makefile
new file mode 100644
index 0000000..b53d999
--- /dev/null
+++ b/uart/bom/dk/Makefile
@@ -0,0 +1,37 @@
+CACHE=query.data
+
+.PHONY: update regen regenerate clean spotless
+
+all: digi-key.dsc digi-key.inv
+
+$(CACHE): digi-key.equ
+ awk '/^#END/ { exit } /^DIGI-KEY / { print $$2 }' \
+ digi-key.equ | \
+ perl ./dk-db.pl query \
+ `[ -r $(CACHE) ] && echo '' -i $(CACHE)` >_$@ || \
+ { rm -f $@ _$@; exit 1; }
+ mv _$@ $@
+
+digi-key.dsc: $(CACHE)
+ perl ./dk-db.pl dsc $(CACHE) >$@ || { rm -f $@; exit 1; }
+
+digi-key.inv: $(CACHE)
+ perl ./dk-db.pl inv $(CACHE) >$@ || { rm -f $@; exit 1; }
+
+update:
+ $(MAKE) clean all
+
+regen regenerate:
+ rm -f digi-key.dsc digi-key.inv
+ $(MAKE) all
+
+clean:
+ rm -f $(CACHE) _$(CACHE)
+
+#
+# we don't do a "make clean" on "make spotless", so that things like "make
+# optimist" don't erase the cache.
+#
+
+spotless:
+ rm -f digi-key.dsc digi-key.inv _$(CACHE)
diff --git a/uart/bom/dk/digi-key.equ b/uart/bom/dk/digi-key.equ
new file mode 100644
index 0000000..ae8702e
--- /dev/null
+++ b/uart/bom/dk/digi-key.equ
@@ -0,0 +1,13 @@
+#EQU
+
+# MCU
+
+DIGI-KEY ATMEGA48-20MMU-ND ATMEL ATMEGA48-20MMU
+
+# LEDs
+
+DIGI-KEY 160-1436-1-ND LITE-ON LTST-C190KRKT
+
+# Header
+
+DIGI-KEY 3M9468-ND 3M 961103-5604-AR
diff --git a/uart/bom/dk/dk-db.pl b/uart/bom/dk/dk-db.pl
new file mode 100755
index 0000000..7e14a9b
--- /dev/null
+++ b/uart/bom/dk/dk-db.pl
@@ -0,0 +1,105 @@
+#!/usr/bin/perl
+
+sub rows
+{
+ local $s = $_[0];
+ my @res = ();
+
+ while ($s =~ m#.*?
(.*?)
#) {
+ push(@res, $1);
+ $s = $';
+ }
+ return @res;
+}
+
+
+sub cols
+{
+ local $s = $_[0];
+ my @res = ();
+
+ while ($s =~ m#.*?]*>(.*?) | #) {
+ push(@res, $1);
+ $s = $';
+ }
+ return @res;
+}
+
+
+sub usage
+{
+ print STDERR "usage: $0 (query [-i cache_file] | dsc | inv) [file ...]\n";
+ exit(1);
+}
+
+
+$mode = shift @ARGV;
+&usage unless $mode eq "query" || $mode eq "dsc" || $mode eq "inv";
+
+if ($mode eq "query") {
+ if ($ARGV[0] eq "-i") {
+ shift @ARGV;
+ $name = shift @ARGV;
+ open(OLD, $name) || die "$name: $!";
+ $q = join("", );
+ ($old = $q) =~ tr/\r\n//d;
+ close OLD;
+ }
+
+ while (<>) {
+ chop;
+ s/#.*//;
+ next if /^\s*$/;
+ next if /^\s/;
+ s/\s.*//;
+ next if $old =~ m#align=right>Digi-Key Part Number$_ | );
+$q =~ tr/\r\n//d;
+
+print "#DSC\n" if $mode eq "dsc";
+print "#INV\n" if $mode eq "inv";
+print "# MACHINE-GENERATED. DO NOT EDIT !\n";
+print "# ", `date -u`;
+
+for (split(/Digi-Key Part Number([^<]+) | Quantity Available]*>([0-9,]+)<#) {
+ ($qty = $1) =~ tr/,//d;
+ }
+ next unless m#align=right>Description | (.*?) | Price Break<(.*?)#;
+ if ($mode eq "dsc") {
+ print "DIGI-KEY $pn $dsc\n";
+ next;
+ }
+ print "DIGI-KEY $pn $qty USD";
+ for (&rows($1)) {
+ @c = &cols($_);
+ next unless $c[0] =~ /^[0-9,]+$/;
+ next unless $c[1] =~ /^[0-9.]+$/;
+ $c[0] =~ tr/,//d;
+ $c[1] =~ tr/,//d; # let's hope we don't need this one often :)
+ $c[1] =~ s/0+$// if $c[1] =~ /\./;
+ print " $c[0] $c[1]";
+ }
+ print "\n";
+}
diff --git a/uart/bom/uart.equ b/uart/bom/uart.equ
new file mode 100644
index 0000000..6073b1d
--- /dev/null
+++ b/uart/bom/uart.equ
@@ -0,0 +1,5 @@
+#EQU
+
+ATMEL ATMEGA48-MMU ATMEL ATMEGA48-20MMU
+
+UART 3M_961103-5604-AR 3M 961103-5604-AR
diff --git a/uart/bom/uart.inv b/uart/bom/uart.inv
new file mode 100644
index 0000000..a534c4b
--- /dev/null
+++ b/uart/bom/uart.inv
@@ -0,0 +1,6 @@
+#INV
+
+# Pseudo-inventory for PCB features.
+
+UART 8:10-card 999999 USD 1 0
+UART PAD_2mm 999999 USD 1 0
diff --git a/uart/bom/uart.sub b/uart/bom/uart.sub
new file mode 100644
index 0000000..4651916
--- /dev/null
+++ b/uart/bom/uart.sub
@@ -0,0 +1,80 @@
+#SUB
+
+# From ben-wpan/bom, which in turn inherited it from gta02-core
+
+-> T=unknown
+
+R[0-9P]* { # also handle RP...
+ -> T=R
+ VAL=*[0-9] -> R=${VAL}R
+ VAL=$R -> R=$VAL
+# -> TOL=5%
+ FN=$% -> TOL=$FN
+}
+
+RP[0-9]* {
+ -> T=RA
+ RP220[123] -> ARRAY=4
+ # the other parameters have already been taken care of by R*
+}
+
+C[0-9]* {
+ -> T=C
+ VAL=*F -> C=$VAL
+ VAL=(*F)/RF -> C=$VAL:1 X=RF # *F/RF "wins" against the *F above
+ FN=*V -> V=>=$FN
+}
+
+L[0-9]* {
+ -> T=L
+ VAL=*H -> L=$VAL
+ FN=*A -> I=>=$FN
+}
+
+B[0-9]* {
+ -> T=FILTER M=BEAD
+ VAL=$R -> R=$VAL
+ FN=*A -> I=$FN
+ FN=*R -> Rdc=$FN
+ FN=0.45R -> Rdc=450mR # hack
+}
+
+D[0-9]* {
+ -> T=D
+ VAL=*F { # heuristic to detect TVS
+ -> M=TVS
+ VAL=*F -> C=<=$VAL
+ FN=(*V)ac -> Vac=$FN:1
+ FN=(*V)dc -> Vdc=$FN:1
+
+ #
+ # Hack: some companies specify the class of varistors with Vdc = 9 V
+ # as Vac = 6.5 V while others use Vac = 7 V. Sometimes, Vac is even
+ # omitted entirely.
+ #
+ # Here, we work around the issue that Karmax use Vac = 6.5 V,
+ # Cooper/Bussmann use Vac = 7V if at all, and out schematics specify
+ # Vac = 6.5 V.
+ #
+ Vac=6.5V {
+ -> Vac=
+ -> Vdc=9V
+ }
+ }
+}
+
+VR[0-9]* -> T=D M=TVS {
+ VAL=$V -> Vdc=$VAL # neither clean nor consistent with the above
+ FN=*F -> C=<=$FN
+}
+
+X[0-9]* {
+ -> T=XTAL
+ VAL=*Hz -> F=$VAL
+ FN=*F -> C=$FN
+ FN=*ppm -> TOL=<=$FN
+}
+
+
+FP=8:10-card -> VAL=8:10-card
+FP=PAD_2mm -> VAL=PAD_2mm
diff --git a/uart/uart.sch b/uart/uart.sch
index f18f5d3..370d3dd 100644
--- a/uart/uart.sch
+++ b/uart/uart.sch
@@ -1,16 +1,15 @@
-EESchema Schematic File Version 2 date Mon Jan 31 21:29:45 2011
+EESchema Schematic File Version 2 date Tue Feb 1 23:39:11 2011
LIBS:power
LIBS:device
LIBS:conn
LIBS:8_10-card
LIBS:atmega48-mmu
-LIBS:uart-cache
EELAYER 24 0
EELAYER END
$Descr A4 11700 8267
Sheet 1 1
Title "External UART (3.3 V) as 8:10 card"
-Date "1 feb 2011"
+Date "2 feb 2011"
Rev "20110131"
Comp "Werner Almesberger"
Comment1 ""
@@ -173,7 +172,7 @@ L LED D1
U 1 1 4D47260E
P 3250 1550
F 0 "D1" H 3250 1650 50 0000 C CNN
-F 1 "LED" H 3250 1450 50 0000 C CNN
+F 1 "LTST-C190KRKT" H 3250 1450 50 0000 C CNN
F 2 "0603" H 3250 1550 60 0001 C CNN
1 3250 1550
-1 0 0 -1
@@ -292,7 +291,9 @@ L CONN_3 K1
U 1 1 4D4704D9
P 2950 950
F 0 "K1" V 2900 950 50 0000 C CNN
-F 1 "CONN_3" V 3000 950 40 0000 C CNN
+F 1 "3M 961103-5604-AR" H 2950 1200 50 0000 C CNN
+F 2 "CONN_3" H 2950 950 60 0001 C CNN
+F 4 "(or any similar 0.1" header)" H 3050 1300 50 0000 C CNN "Field4"
1 2950 950
-1 0 0 1
$EndComp