This demonstrates support for building SMM and other blobs: 
  CP      build/bios.bin
  CC      build/southbridge/intel/i82801gx/smihandler.o
  CC      build/southbridge/intel/i82801gx/smmhandler.o
  AS      build/southbridge/intel/i82801gx/smmhandler.o
  CC      build/southbridge/intel/i82801gx/smm.elf
/usr/bin/ld: warning: .note.gnu.build-id section discarded, --build-id ignored.
  DONE
[rminnich@amd64 coreboot-v3]$ ./build/util/lar/lar l build/coreboot.rom 
  normal/option_table (984 bytes @0x50);loadaddress 0x0 entry 0x0
  normal/initram/segment0 (21856 bytes @0x480);loadaddress 0x0 entry 0x0x3c34
  normal/stage2/segment0 (194824 bytes, zeroes compressed to 1 bytes @0x5a30);loadaddress 0x0x10a60 entry 0x0x2000
  normal/stage2/segment1 (40164 bytes, lzma compressed to 20585 bytes @0x5a90);loadaddress 0x0x2000 entry 0x0x2000
  normal/stage2/segment2 (19040 bytes, lzma compressed to 855 bytes @0xab50);loadaddress 0x0xc000 entry 0x0x2000
  normal/payload/segment0 (30944 bytes, lzma compressed to 18142 bytes @0xaf00);loadaddress 0x0x10000 entry 0x0x100b0
  blob/smm/segment0 (5260 bytes, lzma compressed to 3175 bytes @0xf630);loadaddress 0x0xa0000 entry 0x0
  blob/smm/segment1 (4096 bytes, lzma compressed to 48 bytes @0x102f0);loadaddress 0x0xa7400 entry 0x0
  bootblock (20480 bytes @0xfb000)
Total size = 86814B 84KB (0x1531e)

note the smm blob. It is a pre-parsed ELF file in the standard manner. However, that is entirely
up to the makefile that creates it -- it can be anything. 

Index: southbridge/intel/i82801gx/Makefile

Add support for smm blob creation. 
Index: southbridge/intel/i82801gx/smmhandler.S
Get it to build. 
Index: southbridge/intel/i82801gx/smihandler.c
Get it to build. It needs its own simple printk as it runs
in a different address space. 
Index: mainboard/kontron/986lcd-m/mainboard.h
Add the TTYS0 define. 
Index: mainboard/kontron/986lcd-m/initram.c
Add debug define. 
Fix from Stepan for unitialized variable. 
Index: arch/x86/intel/core2/stage1.c
Fix disable_car so it works. 

Index: arch/x86/Makefile
Fix several things. 
Make rom: the primary target. 
Add BLOB support. 

Index: Makefile
Use rom as the target, not a file. 

Signed-off-by: Ronald G> Minnich <rminnich@gmail.com>

Index: southbridge/intel/i82801gx/Makefile
===================================================================
--- southbridge/intel/i82801gx/Makefile	(revision 1059)
+++ southbridge/intel/i82801gx/Makefile	(working copy)
@@ -54,5 +54,33 @@
 STAGE0_CHIPSET_SRC += \
 					$(src)/southbridge/intel/i82801gx/stage1_smbus.c \
 					$(src)/southbridge/intel/i82801gx/libsmbus.c \
+# The SMM blob
+BLOBS += $(obj)/southbridge/intel/i82801gx/smm.elf
+		
+$(obj)/southbridge/intel/i82801gx/smmhandler.o:	$(src)/southbridge/intel/i82801gx/smmhandler.S
+	$(Q)mkdir -p $(dir $@)
+	$(Q)printf "  CC      $(subst $(shell pwd)/,,$(@))\n"
+	$(Q)$(CC) -E $(COREBOOTINCLUDE) -I$(src)/northbridge/intel/i945 $< \
+		-o $(obj)/southbridge/intel/i82801gx/smmhandler.s 
+	$(Q)printf "  AS      $(subst $(shell pwd)/,,$(@))\n"
+	$(Q)$(AS) $(obj)/southbridge/intel/i82801gx/smmhandler.s -o $@
 
+# can't really do a dependency on a lar object.
+
+SMMSRC=$(src)/southbridge/intel/i82801gx/smihandler.c 
+
+SMMOBJ := $(obj)/southbridge/intel/i82801gx/smihandler.o \
+		$(obj)/lib/vtxprintf.o \
+		$(obj)/lib/string.o \
+		$(obj)/lib/mem.o \
+		 $(obj)/southbridge/intel/i82801gx/smmhandler.o
+
+$(obj)/southbridge/intel/i82801gx/smm.elf:$(src)/southbridge/intel/i82801gx/smm.ld \
+			$(SMMOBJ)
+			$(Q)printf "  CC      $(subst $(shell pwd)/,,$(@))\n"
+			$(Q)$(CC) -nostdlib -static -T $< -o $@ $(SMMOBJ) 
+			$(Q)$(obj)/util/lar/lar -e $(COMPRESSFLAG) -a \
+				$(obj)/coreboot.rom $(obj)/southbridge/intel/i82801gx/smm.elf:blob/smm;
+
+
 endif
Index: southbridge/intel/i82801gx/smmhandler.S
===================================================================
--- southbridge/intel/i82801gx/smmhandler.S	(revision 1059)
+++ southbridge/intel/i82801gx/smmhandler.S	(working copy)
@@ -52,7 +52,7 @@
  *
  */
 
-#include <arch/asm.h>
+#define ASSEMBLY
 
 #define LAPIC_ID 0xfee00020
 
Index: southbridge/intel/i82801gx/smihandler.c
===================================================================
--- southbridge/intel/i82801gx/smihandler.c	(revision 1059)
+++ southbridge/intel/i82801gx/smihandler.c	(working copy)
@@ -19,15 +19,17 @@
  * MA 02110-1301 USA
  */
 
-#include <arch/io.h>
-#include <arch/romcc_io.h>
-#include <console/console.h>
-#include <cpu/x86/cache.h>
-#include <cpu/x86/smm.h>
-#include "chip.h"
+#include <mainboard.h>
+#include <device/pci_def.h>
+#include  <io.h>
+#include <console.h>
+#include <cpu.h>
+#include <smm.h>
+#include <stdarg.h>
 
 // Future TODO: Move to i82801gx directory
 #include "../../../northbridge/intel/i945/ich7.h"
+#include "../../../northbridge/intel/i945/i945.h"
 
 #define DEBUG_SMI
 
@@ -293,6 +295,8 @@
 #define UART_MSR 0x06
 #define UART_SCR 0x07
 
+int console_loglevel = 8;
+
 static int uart_can_tx_byte(void)
 {
 	return inb(TTYS0_BASE + UART_LSR) & 0x20;
@@ -323,18 +327,35 @@
 	uart_wait_to_tx_byte();
 }
 
-void console_tx_byte(unsigned char byte)
+void console_tx_byte(unsigned char byte, void *arg)
 {
 	if (byte == '\n')
 		uart_tx_byte('\r');
 	uart_tx_byte(byte);
 }
 
+int printk(int msg_level, const char *fmt, ...)
+{
+	int vtxprintf(void (*tx_byte)(unsigned char byte, void *arg), void *arg, const char *fmt, va_list args);
+
+	va_list args;
+	int i = 0;
+
+	if (msg_level > console_loglevel) {
+		return 0;
+	}
+
+	va_start(args, fmt);
+	i += vtxprintf(console_tx_byte, (void *)0, fmt, args);
+	va_end(args);
+
+	return i;
+}
 /* We are using PCIe accesses for now
  *  1. the chipset can do it
  *  2. we don't need to worry about how we leave 0xcf8/0xcfc behind
  */
-#include "../../../northbridge/intel/i945/pcie_config.c"
+#include "../../../northbridge/intel/i945/pcie_config.h"
 
 /* ********************* smi_util ************************* */
 
@@ -405,11 +426,10 @@
 	node=nodeid();
 
 #ifdef DEBUG_SMI
-	console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
+	console_loglevel = CONFIG_DEFAULT_CONSOLE_LOGLEVEL;
 #else
 	console_loglevel = 1;
 #endif
-
 	printk(BIOS_DEBUG, "\nSMI# #%d\n", node);
 
 	switch (smm_revision) {
@@ -432,7 +452,7 @@
 		return;
 	}
 
-	pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
+	pmbase = pcie_read_config16(PCI_BDF(0, 0x1f, 0), 0x40) & 0xfffc;
 	printk(BIOS_SPEW, "SMI#: pmbase = 0x%04x\n", pmbase);
 	
 	/* We need to clear the SMI status registers, or we won't see what's
@@ -443,15 +463,17 @@
 
 	if (smi_sts & (1 << 21)) { // MONITOR
 		global_nvs_t *gnvs = (global_nvs_t *)0xc00;
-		int i;
 		u32 reg32;
 
 		reg32 = RCBA32(0x1e00); // TRSR - Trap Status Register
 #if 0
-		/* Comment in for some useful debug */
-		for (i=0; i<4; i++) {
-			if (reg32 & (1 << i)) {
-				printk(BIOS_DEBUG, "  io trap #%d\n", i);
+		{
+			int i;
+			/* Comment in for some useful debug */
+			for (i=0; i<4; i++) {
+				if (reg32 & (1 << i)) {
+					printk(BIOS_DEBUG, "  io trap #%d\n", i);
+				}
 			}
 		}
 #endif
@@ -484,7 +506,7 @@
 		if (tco_sts & (1 << 8)) { // BIOSWR
 			u8 bios_cntl;
 
-			bios_cntl = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc);
+			bios_cntl = pcie_read_config16(PCI_BDF(0, 0x1f, 0), 0xdc);
 
 			if (bios_cntl & 1) {
 				/* BWE is RW, so the SMI was caused by a
@@ -498,7 +520,7 @@
 				 * box.
 				 */
 				printk(BIOS_DEBUG, "Switching back to RO\n");
-				pcie_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1));
+				pcie_write_config32(PCI_BDF(0, 0x1f, 0), 0xdc, (bios_cntl & ~1));
 			} /* No else for now? */
 		}
 	}
@@ -536,7 +558,7 @@
 	if (smi_sts & (1 << 4)) { // SLP_SMI
 		u32 reg32;
 		reg32 = inl(pmbase + 0x04);
-		printk(BIOS_DEBUG, "SMI#: SLP = 0x%08x\n");
+		printk(BIOS_DEBUG, "SMI#: SLP = 0x%08x\n", reg32);
 		printk(BIOS_DEBUG, "SMI#: Powering off.\n");
 		outl((6 << 10), pmbase + 0x04);
 		outl((1 << 13) | (6 << 10), pmbase + 0x04);
Index: mainboard/kontron/986lcd-m/mainboard.h
===================================================================
--- mainboard/kontron/986lcd-m/mainboard.h	(revision 1059)
+++ mainboard/kontron/986lcd-m/mainboard.h	(working copy)
@@ -31,3 +31,4 @@
 /* nowhere else to go yet */
 #define TEST_SMM_FLASH_LOCKDOWN 0
 
+#define TTYS0_BASE 0x3f8
\ No newline at end of file
Index: mainboard/kontron/986lcd-m/initram.c
===================================================================
--- mainboard/kontron/986lcd-m/initram.c	(revision 1059)
+++ mainboard/kontron/986lcd-m/initram.c	(working copy)
@@ -18,7 +18,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
-
+#define DEBUG_RAM_SETUP 
 #define _MAINOBJECT
 
 #include <mainboard.h>
@@ -157,7 +157,7 @@
  */
 int main(void)
 {
-	int boot_mode;
+	int boot_mode=0;
 	void i945_early_initialization(void);
 	void enable_smbus(void);
 	int fixup_i945_errata(void);
Index: arch/x86/intel/core2/stage1.c
===================================================================
--- arch/x86/intel/core2/stage1.c	(revision 1059)
+++ arch/x86/intel/core2/stage1.c	(working copy)
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2008 Carl-Daniel Hailfinger
+ * Copyright (C) 2008 coresystems GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,30 +30,23 @@
 #include <string.h>
 #include <mtrr.h>
 
-/**
- * Disable Cache As RAM (CAR) after memory is setup.
- */
 void disable_car(void)
 {
-	printk(BIOS_DEBUG, "disable_car entry\n");
-	/* Determine new global variable location. Stack organization from top
-	 * Top 4 bytes are reserved
-	 * Pointer to global variables
-	 * Global variables
-	 *
- 	 * Align the result to 8 bytes
-	 */
-	struct global_vars *const newlocation = (struct global_vars *)((RAM_STACK_BASE - sizeof(struct global_vars *) - sizeof(struct global_vars)) & ~0x7);
-	/* Copy global variables to new location. */
-	memcpy(newlocation, global_vars(), sizeof(struct global_vars));
-	printk(BIOS_DEBUG, "disable_car global_vars copy done\n");
-	/* Set the new global variable pointer. */
-	*(struct global_vars **)(RAM_STACK_BASE - sizeof(struct global_vars *)) = newlocation;
+	struct global_vars *const new_globals = 
+		(struct global_vars *)((RAM_STACK_BASE - sizeof(struct global_vars *) - sizeof(struct global_vars)) & ~0x7);
 
-	printk(BIOS_DEBUG, "disable_car global_vars pointer adjusted\n");
-	printk(BIOS_DEBUG, "entering asm code now\n");
+	/* Copy global variables */
+	memcpy(new_globals, global_vars(), sizeof(struct global_vars));
 
+	/* Update global variable pointer */
+	*(struct global_vars **)(RAM_STACK_BASE - sizeof(struct global_vars *))
+		= new_globals;
+
+	printk(BIOS_DEBUG, "Disabling cache-as-ram\n");
+
 	__asm__ __volatile__(
+"movb   $0x30, %%al\noutb %%al, $0x80\n"
+
 	"	movl	%[newesp], %%esp	\n"
 
 	/* We don't need cache as ram for now on */
@@ -61,6 +55,8 @@
 	"	orl    $(0x1<<30),%%eax		\n"
 	"	movl    %%eax, %%cr0		\n"
 
+"movb   $0x31, %%al\noutb %%al, $0x80\n"
+
 	/* disable fixed mtrr from now on, it will be enabled by coreboot_ram again*/
 	/* clear sth */
 	"	xorl    %%eax, %%eax		\n"
@@ -70,6 +66,7 @@
 	"	movl    $0x200, %%ecx		\n"
 	"	wrmsr				\n"
 
+"movb   $0x32, %%al\noutb %%al, $0x80\n"
 	/* Set the default memory type and disable fixed and enable variable MTRRs */
 	"	movl    %[_MTRRdefType_MSR], %%ecx	\n"
 	"	xorl    %%edx, %%edx		\n"
@@ -77,17 +74,22 @@
 	"	movl    $0x00000800, %%eax	\n"
 	"	wrmsr				\n"
 
+"movb   $0x33, %%al\noutb %%al, $0x80\n"
 	/* enable cache */
 	"	movl    %%cr0, %%eax		\n"
 	"	andl    $0x9fffffff,%%eax	\n"
 	"	movl    %%eax, %%cr0		\n"
 
-	"	wbinvd				\n"
+"movb   $0x34, %%al\noutb %%al, $0x80\n"
+	"	invd				\n"
 
+"movb   $0x35, %%al\noutb %%al, $0x80\n"
 	"	call stage1_phase3		\n"
-	:: [newesp] "i" (newlocation),
+	:: [newesp] "i" (new_globals),
 	 [_MTRRdefType_MSR] "i" (MTRRdefType_MSR)
 	: "memory");
+
+	printk(BIOS_DEBUG, "Something went wrong. Still here.\n");
 }
 
 void stop_ap(void)
Index: arch/x86/Makefile
===================================================================
--- arch/x86/Makefile	(revision 1059)
+++ arch/x86/Makefile	(working copy)
@@ -48,6 +48,13 @@
 COMPRESSFLAG := -C nrv2b
 endif
 
+# all depends on coreboot.rom and BLOBS. 
+# BLOBS may be empty. They are things such as smm that are searched for at runtime. 
+# They depend on the coreboot rom existing so that they can be placed there. 
+# The name of the blob is determined by the various blob rules. There is so much possible 
+# variation in them that it is not really possible to put a standard rule in this file. 
+rom:: $(obj)/coreboot.rom $(BLOBS) 
+
 $(obj)/coreboot.rom $(obj)/coreboot.map: $(obj)/coreboot.bootblock $(obj)/util/lar/lar lzma nrv2b $(obj)/coreboot.initram $(obj)/coreboot.stage2 $(obj)/option_table
 	$(Q)printf "  LAR     $(subst $(shell pwd)/,,$(@))\n"
 	$(Q)rm -f $(obj)/coreboot.rom
@@ -306,4 +313,4 @@
 	$(Q)cp cscope.proj $(obj)/mainboard/$(MAINBOARDDIR)/kscope
 	$(Q)sh util/mkdep $@ $(INITCFLAGS) "--" $(ALLSRC)
 #	$(Q)sort -u -o $@ $@
-
+.PHONY: rom
Index: Makefile
===================================================================
--- Makefile	(revision 1059)
+++ Makefile	(working copy)
@@ -77,7 +77,7 @@
 COREBOOT_EXTRA_VERSION := -$(shell echo $(CONFIG_LOCALVERSION))
 endif
 
-all: prepare prepare2 $(obj)/coreboot.rom
+all: prepare prepare2 rom
 	$(Q)printf "  DONE\n"
 
 ARCH:=$(shell echo $(CONFIG_ARCH))
@@ -166,5 +166,5 @@
 	$(Q)printf "  CC      $(subst $(shell pwd)/,,$(@))\n"
 	$(Q)$(CC) $(CFLAGS) -o $@ -c $<
 
-.PHONY: doc doxygen depends prepare prepare2 clean distclean
+.PHONY: doc doxygen depends prepare prepare2 clean distclean 
 
