mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCHv2 00/14] Bring in basic x86 support into 'barebox'
@ 2010-01-12 10:15 Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 01/14] Add a tool to activate barebox as a boot loader on x86 architectures Juergen Beisert
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

This patch series brings in some basic x86 support into the tree.
At first this support can act as a boot loader on a BIOS based
x86 machine like GRUB is. E.g. barebox will be stored in the MBR of
a boot media the BIOS supports to boot from. This implementation still
talks to the BIOS in real mode, to load or store data from/to a disk
drive, but the barebox core itself runs in 32 bit flat mode.

Currently only a serial console is supported.

v2 of this patch series comes with some clean ups and also uses the discussed
naming convention for BIOS based disk access. The whole series is updated to
'barebox' (instead of u-boot-v2). Note: Its tested only with QEMU yet. We are
going to port it to real hardware now.

Comments are welcome.

jbe


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 01/14] Add a tool to activate barebox as a boot loader on x86 architectures
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 02/14] Consider real and protected mode in the dump file Juergen Beisert
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_install_tool.diff --]
[-- Type: text/plain, Size: 26044 bytes --]

To use barebox as a BIOS based bootloader for x86 architectures, the binary
must be patched to get it bootstrapped at runtime. The 'setupmbr' tool installs
the barebox-binary to the given device node or image file and patch it in
accordance to the needed sector information at runtime.

Signed-off by: Juergen Beisert <jbe@pengutronix.de>

---
 Doxyfile                    |    3 
 scripts/Makefile            |    4 
 scripts/setupmbr/Makefile   |    4 
 scripts/setupmbr/arch.h     |   55 +++
 scripts/setupmbr/setupmbr.c |  705 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 769 insertions(+), 2 deletions(-)

Index: barebox-2009.12.0/scripts/Makefile
===================================================================
--- barebox-2009.12.0.orig/scripts/Makefile
+++ barebox-2009.12.0/scripts/Makefile
@@ -14,5 +14,7 @@ always		:= $(hostprogs-y) $(hostprogs-m)
 
 subdir-y                     += mod
 
+subdir-$(CONFIG_X86)             += setupmbr
+
 # Let clean descend into subdirs
-subdir-	+= basic kconfig
+subdir-	+= basic kconfig setupmbr
Index: barebox-2009.12.0/scripts/setupmbr/Makefile
===================================================================
--- /dev/null
+++ barebox-2009.12.0/scripts/setupmbr/Makefile
@@ -0,0 +1,4 @@
+HOST_EXTRACFLAGS=-I$(srctree)
+
+hostprogs-y  := setupmbr
+always       := $(hostprogs-y)
Index: barebox-2009.12.0/scripts/setupmbr/arch.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/scripts/setupmbr/arch.h
@@ -0,0 +1,55 @@
+
+/* we need the one from the host */
+#include <endian.h>
+#include <stdint.h>
+
+/* Byte-orders.  */
+#define swap16(x)	\
+({ \
+   uint16_t _x = (x); \
+   (uint16_t) ((_x << 8) | (_x >> 8)); \
+})
+
+#define swap32(x)	\
+({ \
+   uint32_t _x = (x); \
+   (uint32_t) ((_x << 24) \
+                    | ((_x & (uint32_t) 0xFF00UL) << 8) \
+                    | ((_x & (uint32_t) 0xFF0000UL) >> 8) \
+                    | (_x >> 24)); \
+})
+
+#define swap64(x)	\
+({ \
+   uint64_t _x = (x); \
+   (uint64_t) ((_x << 56) \
+                    | ((_x & (uint64_t) 0xFF00ULL) << 40) \
+                    | ((_x & (uint64_t) 0xFF0000ULL) << 24) \
+                    | ((_x & (uint64_t) 0xFF000000ULL) << 8) \
+                    | ((_x & (uint64_t) 0xFF00000000ULL) >> 8) \
+                    | ((_x & (uint64_t) 0xFF0000000000ULL) >> 24) \
+                    | ((_x & (uint64_t) 0xFF000000000000ULL) >> 40) \
+                    | (_x >> 56)); \
+})
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+
+/* Our target is a ia32 machine, always little endian */
+
+# define host2target_16(x)	swap16(x)
+# define host2target_32(x)	swap32(x)
+# define host2target_64(x)	swap64(x)
+# define target2host_16(x)	swap16(x)
+# define target2host_32(x)	swap32(x)
+# define target2host_64(x)	swap64(x)
+
+#else
+
+# define host2target_16(x)	(x)
+# define host2target_32(x)	(x)
+# define host2target_64(x)	(x)
+# define target2host_16(x)	(x)
+# define target2host_32(x)	(x)
+# define target2host_64(x)	(x)
+
+#endif
Index: barebox-2009.12.0/scripts/setupmbr/setupmbr.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/scripts/setupmbr/setupmbr.c
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Write the barebox binary to the MBR and the following disk sectors
+ *
+ * Also patch dedicated locations in the image to make it work at runtime
+ *
+ * Current restrictions are:
+ * - only installs into MBR and the sectors after it
+ * - tested only with QEMU
+ * - and maybe some others
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+/* include the info from this barebox release */
+#include "include/linux/utsrelease.h"
+#include "arch/x86/include/asm/barebox.lds.h"
+
+/** define to disable integrity tests and debug messages */
+#define NDEBUG
+
+/* some infos about our target architecture */
+#include "arch.h"
+
+/**
+ * "Disk Address Packet Structure" to be used when calling int13,
+ * function 0x42
+ *
+ * @note All entries are in target endianess
+ */
+struct DAPS
+{
+	uint8_t size;		/**< size of this data set, 0 marks it as invalid */
+	uint8_t res1;		/**< always 0 */
+	int8_t count;		/**< number of sectors 0...127 to handle */
+	uint8_t res2;		/**< always 0 */
+	uint16_t offset;	/**< store address: offset */
+	uint16_t segment;	/**< store address: segment */
+	uint64_t lba;		/**< start sector number in LBA */
+} __attribute__ ((packed));
+
+/**
+ * Description of one partition table entry (D*S type)
+ *
+ * @note All entries are in target endianess
+ */
+struct partition_entry {
+	uint8_t boot_indicator;
+	uint8_t chs_begin[3];
+	uint8_t type;
+	uint8_t chs_end[3];
+	uint32_t partition_start;	/* LE */
+	uint32_t partition_size;	/* LE */
+} __attribute__ ((packed));
+
+#ifndef NDEBUG
+static void debugout(const struct DAPS *entry, int supress_entry)
+{
+	if (supress_entry)
+		printf("DAPS entry: ");
+	else
+		printf("DAPS entry % 3u: ", ((unsigned)entry & ( SECTOR_SIZE - 1)) / sizeof(struct DAPS));
+
+	printf("Size: % 2u, Count: % 3d, Offset: 0x%04hX, Segment: 0x%04hX, LBA: %llu\n",
+		entry->size, entry->count,
+		target2host_16(entry->offset), target2host_16(entry->segment),
+		target2host_64(entry->lba));
+}
+#else
+# define debugout(x,y) (__ASSERT_VOID_CAST(0))
+#endif
+
+/**
+ * Fill *one* DAPS
+ * @param sector The DAPS to fill
+ * @param count Sector count
+ * @param offset Realmode offset in the segment
+ * @param segment Real mode segment
+ * @param lba LBA of the first sector to read
+ * @return 0 on success
+ */
+static int fill_daps(struct DAPS *sector, unsigned count, unsigned offset, unsigned segment, uint64_t lba)
+{
+	assert(sector != NULL);
+	assert(count < 128);
+	assert(offset < 0x10000);
+	assert(segment < 0x10000);
+
+	sector->size = sizeof(struct DAPS);
+	sector->res1 = 0;
+	sector->count = (int8_t)count;
+	sector->res2 = 0;
+	sector->offset = host2target_16(offset);
+	sector->segment = host2target_16(segment);
+	sector->lba = host2target_64(lba);
+
+	return 0;
+}
+
+/**
+ * Mark a DAPS invalid to let the boot loader code stop at this entry.
+ * @param sector The DAPS to be marked as invalid
+ *
+ * Marking as invalid must be done in accordance to the detection method
+ * the assembler routine in the boot loader uses:
+ * The current code tests for zero in the first two bytes of the DAPS.
+ */
+static void invalidate_daps(struct DAPS *sector)
+{
+	sector->size = MARK_DAPS_INVALID;
+	sector->res1 = 0;
+}
+
+/**
+ * Create the indirect sector with the DAPS entries
+ * @param daps_table Where to store the entries
+ * @param size Size of the whole image in bytes
+ * @param pers_sector_count Count of sectors to skip after MBR for the persistant environment storage
+ * @return 0 on success
+ *
+ * This routine calculates the DAPS entries for the case the whole
+ * barebox images fits into the MBR itself and the sectors after it.
+ * This means the start of the first partition must keep enough sectors
+ * unused.
+ * It also skips 'pers_sector_count' sectors after the MBR for special
+ * usage if given.
+ */
+static int barebox_linear_image(struct DAPS *daps_table, off_t size, long pers_sector_count)
+{
+	unsigned offset = LOAD_AREA, next_offset;
+	unsigned segment = LOAD_SEGMENT;
+	unsigned chunk_size, i = 0;
+	uint64_t lba = 2 + pers_sector_count;
+	int rc;
+
+	/*
+	 * We can load up to 127 sectors in one chunk. What a bad number...
+	 * So, we will load in chunks of 32 kiB.
+	 */
+
+	/* at runtime two sectors from the image are already loaded: MBR and indirect */
+	size -= 2 * SECTOR_SIZE;
+	/* and now round up to multiple of sector size */
+	size = (size + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);
+
+	/*
+	 * The largest image we can load with this method is:
+	 * (SECTOR_SIZE / sizeof(DAPS) - 1) * 32 kiB
+	 * For a 512 byte sector and a 16 byte DAPS:
+	 * (512 / 16 - 1) * 32 kiB = 992 kiB
+	 * Note: '- 1' to consider one entry is required to pad to a 32 kiB boundary
+	 */
+
+	if (size >= (SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32 * 1024) {
+		fprintf(stderr, "Image too large to boot. Max size is %zu kiB, image size is %lu kiB\n",
+			(SECTOR_SIZE / sizeof(struct DAPS) - 1) * 32, size / 1024);
+		return -1;
+	}
+
+	if (size > 32 * 1024) {
+		/* first fill up until the next 32 k boundary */
+		next_offset = (offset + 32 * 1024 -1) & ~0x7fff;
+		chunk_size = next_offset - offset;
+		if (chunk_size & (SECTOR_SIZE-1)) {
+			fprintf(stderr, "Unable to pad from %X to %X in multiple of sectors\n", offset, next_offset);
+			return -1;
+		}
+
+		rc = fill_daps(&daps_table[i], chunk_size / SECTOR_SIZE, offset, segment, lba);
+		if (rc != 0)
+			return -1;
+		debugout(&daps_table[i], 0);
+
+		/* calculate values to enter the loop for the other entries */
+		size -= chunk_size;
+		i++;
+		lba += chunk_size / SECTOR_SIZE;
+		offset += chunk_size;
+		if (offset >= 0x10000) {
+			segment += 4096;
+			offset = 0;
+		}
+
+		/*
+		 * Now load the remaining image part in 32 kiB chunks
+		 */
+		while (size) {
+			if (size >= 32 * 1024 ) {
+				if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) {
+					fprintf(stderr, "Internal tool error: Too many DAPS entries!\n");
+					return -1;
+				}
+				rc = fill_daps(&daps_table[i], 64, offset, segment, lba);
+				if (rc != 0)
+					return -1;
+				debugout(&daps_table[i], 0);
+
+				size -= 32 * 1024;
+				lba += 64;
+				offset += 32 * 1024;
+				if (offset >= 0x10000) {
+					segment += 4096;
+					offset = 0;
+				}
+				i++;
+			} else {
+				if (i >= (SECTOR_SIZE / sizeof(struct DAPS))) {
+					fprintf(stderr, "Internal tool error: Too many DAPS entries!\n");
+					return -1;
+				}
+				rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba);
+				if (rc != 0)
+					return -1;
+				debugout(&daps_table[i], 0);
+				size = 0;	/* finished */
+				i++;
+			}
+		};
+	} else {
+		/* less than 32 kiB. Very small image... */
+		rc = fill_daps(&daps_table[i], size / SECTOR_SIZE, offset, segment, lba);
+		if (rc != 0)
+			return -1;
+		debugout(&daps_table[i], 0);
+		i++;
+	}
+
+	/*
+	 * Do not mark an entry as invalid if the buffer is full. The
+	 * boot code stops if all entries of a buffer are read.
+	 */
+	if (i >= (SECTOR_SIZE / sizeof(struct DAPS)))
+		return 0;
+
+	/* mark the last DAPS invalid */
+	invalidate_daps(&daps_table[i]);
+	debugout(&daps_table[i], 0);
+
+	return 0;
+}
+
+/**
+ * Do some simple sanity checks if this sector could be an MBR
+ * @param sector Sector with data to check
+ * @param size Size of the buffer
+ * @return 0 if successfull
+ */
+static int check_for_valid_mbr(const uint8_t *sector, off_t size)
+{
+	if (size < SECTOR_SIZE) {
+		fprintf(stderr, "MBR too small to be valid\n");
+		return -1;
+	}
+
+	if ((sector[OFFSET_OF_SIGNATURE] != 0x55) ||
+		(sector[OFFSET_OF_SIGNATURE + 1] != 0xAA)) {
+		fprintf(stderr, "No MBR signature found\n");
+		return -1;
+	}
+
+	/* FIXME: try to check if there is a valid partition table */
+	return 0;
+}
+
+/**
+ * Check space between start of the image and the start of the first partition
+ * @param hd_image HD image to examine
+ * @param size Size of the barebox image
+ * @return 0 on success, -1 if the barebox image is too large
+ */
+static int check_for_space(const void *hd_image, off_t size)
+{
+	struct partition_entry *partition;
+	uint8_t *mbr_disk_sector = (uint8_t*)hd_image;
+	off_t spare_sector_count;
+
+	assert(hd_image != NULL);
+	assert(size > 0);
+
+	if (check_for_valid_mbr(hd_image, size) != 0)
+		return -1;
+
+	/* where to read */
+	partition = (struct partition_entry*) &mbr_disk_sector[OFFSET_OF_PARTITION_TABLE];
+
+	/* TODO describes the first entry always the first partition? */
+	spare_sector_count = target2host_32(partition->partition_start);
+
+#ifdef DEBUG
+	printf("Debug: Required free sectors for barebox prior first partition: %lu, hd image provides: %lu\n",
+		(size + SECTOR_SIZE - 1) / SECTOR_SIZE, spare_sector_count);
+#endif
+	spare_sector_count *= SECTOR_SIZE;
+	if (spare_sector_count < size) {
+		fprintf(stderr, "Not enough space after MBR to store barebox\n");
+		fprintf(stderr, "Move begin of the first partition beyond sector %lu\n", (size + SECTOR_SIZE - 1) / SECTOR_SIZE);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Setup the persistant environment storage information
+ * @param patch_area Where to patch
+ * @param pers_sector_start Start sector of the persistant environment storage
+ * @param pers_sector_count Count of sectors for the persistant environment storage
+ * @return 0 on success
+ */
+static int store_pers_env_info(void *patch_area, uint64_t pers_sector_start, long pers_sector_count)
+{
+	uint64_t *start_lba = (uint64_t*)(patch_area + PATCH_AREA_PERS_START);
+	uint16_t *count_lba = (uint16_t*)(patch_area + PATCH_AREA_PERS_SIZE);
+
+	assert(patch_area != NULL);
+	assert(pers_sector_count >= 0);
+
+	if (pers_sector_count == 0) {
+		*count_lba = host2target_16(PATCH_AREA_PERS_SIZE_UNUSED);
+		return 0;
+	}
+
+	*start_lba = host2target_64(pers_sector_start);
+	*count_lba = host2target_16(pers_sector_count);
+
+	return 0;
+}
+
+/**
+ * Prepare the MBR and indirect sector for runtime
+ * @param fd_barebox barebox image to use
+ * @param fd_hd Hard disk image to prepare
+ * @param pers_sector_count Count of sectors to skip after MBR for the persistant environment storage
+ * @return 0 on success
+ *
+ * This routine expects a prepared hard disk image file with a partition table
+ * in its first sector. This method only is currently supported.
+ */
+static int barebox_overlay_mbr(int fd_barebox, int fd_hd, long pers_sector_count)
+{
+	const void *barebox_image;
+	void *hd_image;
+	int rc;
+	struct stat sb;
+	struct DAPS *embed;	/* part of the MBR */
+	struct DAPS *indirect;	/* sector with indirect DAPS */
+	off_t required_size;
+
+	if (fstat(fd_barebox, &sb) == -1) {
+		perror("fstat");
+		return -1;
+	}
+
+	/* the barebox image won't be touched */
+	barebox_image = mmap(NULL, sb.st_size,  PROT_READ, MAP_SHARED, fd_barebox, 0);
+	if (barebox_image == MAP_FAILED) {
+		perror("mmap");
+		return -1;
+	}
+
+	rc = check_for_valid_mbr(barebox_image, sb.st_size);
+	if (rc != 0) {
+		fprintf(stderr, "barebox image seems not valid: Bad MBR signature\n");
+		goto on_error_hd;
+	}
+
+	/*
+	 * the persistant environment storage is in front of the main
+	 * barebox image. To handle both, we need more space in front of the
+	 * the first partition.
+	 */
+	required_size = sb.st_size + pers_sector_count * SECTOR_SIZE;
+
+	/* the hd image will be modified */
+	hd_image = mmap(NULL, required_size,  PROT_READ | PROT_WRITE,
+					MAP_SHARED, fd_hd, 0);
+	if (hd_image == MAP_FAILED) {
+		perror("mmap");
+		rc = -1;
+		goto on_error_hd;
+	}
+
+	/* check for space */
+	rc = check_for_space(hd_image, required_size);
+	if (rc != 0)
+		goto on_error_space;
+
+	/* embed barebox's boot code into the disk drive image */
+	memcpy(hd_image, barebox_image, OFFSET_OF_PARTITION_TABLE);
+
+	/*
+	 * embed the barebox main image into the disk drive image,
+	 * but keep the persistant environment storage untouched
+	 * (if defined), e.g. store the main image behind this special area.
+	 */
+	memcpy(hd_image + ((pers_sector_count + 1) * SECTOR_SIZE),
+			barebox_image + SECTOR_SIZE, sb.st_size - SECTOR_SIZE);
+
+	/* now, prepare this hard disk image for BIOS based booting */
+	embed = hd_image + PATCH_AREA;
+	indirect = hd_image + ((pers_sector_count + 1) * SECTOR_SIZE);
+
+	/*
+	 * Fill the embedded DAPS to let the basic boot code find the
+	 * indirect sector at runtime
+	 */
+#ifdef DEBUG
+	printf("Debug: Fill in embedded DAPS\n");
+#endif
+	rc = fill_daps(embed, 1, INDIRECT_AREA, INDIRECT_SEGMENT,
+				1 + pers_sector_count);
+	if (rc != 0)
+		goto on_error_space;
+	debugout(embed, 1);
+
+#ifdef DEBUG
+	printf("Debug: Fill in indirect sector\n");
+#endif
+	/*
+	 * fill the indirect sector with the remaining DAPS to load the
+	 * whole barebox image at runtime
+	 */
+	rc = barebox_linear_image(indirect, sb.st_size, pers_sector_count);
+	if (rc != 0)
+		goto on_error_space;
+
+	/*
+	 * TODO: Replace the fixed LBA starting number by a calculated one,
+	 * to support barebox as a chained loader in a different start
+	 * sector than the MBR
+	 */
+	rc = store_pers_env_info(embed, 1, pers_sector_count);
+	if (rc != 0)
+		goto on_error_space;
+
+on_error_space:
+	munmap(hd_image, required_size);
+
+on_error_hd:
+	munmap((void*)barebox_image, sb.st_size);
+
+	return rc;
+}
+
+static void print_usage(const char *pname)
+{
+	printf("%s: Preparing a hard disk image for boot with barebox on x86.\n", pname);
+	printf("Usage is\n %s [options] -m <barebox image> -d <hd image>\n", pname);
+	printf(" [options] are:\n -s <count> sector count of the persistant environment storage\n");
+	printf(" <barebox image> barebox's boot image file\n");
+	printf(" <hd image> HD image to store the barebox image\n");
+	printf(" If no '-s <x>' was given, barebox occupies sectors 0 to n, else sector 0 and x+1 to n\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int rc = 0, c;
+	char *barebox_image_filename = NULL, *hd_image_filename = NULL;
+	int fd_barebox_image = 0, fd_hd_image = 0;
+	long barebox_pers_size = -1;
+
+	if (argc == 1) {
+		print_usage(argv[0]);
+		exit(0);
+	}
+
+	/* handle command line options first */
+	while (1) {
+		c = getopt(argc, argv, "m:d:s:hv");
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 's':
+			barebox_pers_size = strtol(optarg, NULL, 0);
+			break;
+		case 'm':
+			barebox_image_filename = strdup(optarg);
+			break;
+		case 'd':
+			hd_image_filename = strdup(optarg);
+			break;
+		case 'h':
+			print_usage(argv[0]);
+			rc = 0;
+			goto on_error;
+		case 'v':
+			printf("setupmbr for u-boot-v%s\n", UTS_RELEASE);
+			printf("Send bug reports to 'barebox@lists.infradead.org'\n");
+			rc = 0;
+			goto on_error;
+		}
+	}
+
+	if (barebox_image_filename == NULL) {
+		print_usage(argv[0]);
+		rc = -1;
+		goto on_error;
+	}
+
+	fd_barebox_image = open(barebox_image_filename, O_RDONLY);
+	if (fd_barebox_image == -1) {
+		fprintf(stderr, "Cannot open '%s' for reading\n",
+				barebox_image_filename);
+		rc = -1;
+		goto on_error;
+	}
+
+	fd_hd_image = open(hd_image_filename, O_RDWR);
+	if (fd_hd_image == -1) {
+		fprintf(stderr, "Cannot open '%s'\n", hd_image_filename);
+		rc = -1;
+		goto on_error;
+	}
+
+	if (barebox_pers_size < 0)
+		barebox_pers_size = 0;
+
+	rc = barebox_overlay_mbr(fd_barebox_image, fd_hd_image, barebox_pers_size);
+
+on_error:
+	if (fd_barebox_image != -1)
+		close(fd_barebox_image);
+	if (fd_hd_image != -1)
+		close(fd_hd_image);
+
+	if (barebox_image_filename != NULL)
+		free(barebox_image_filename);
+	if (hd_image_filename != NULL)
+		free(hd_image_filename);
+
+	return rc;
+}
+
+/** @page x86_bootloader barebox acting as PC bootloader
+
+@section x86_bootloader_features Features
+
+@a barebox can act as a bootloader for PC based systems. In this case a special
+binary layout will be created to be able to store it on some media the PC
+BIOS can boot from. It can boot Linux kernels stored also on the same boot
+media and be configured at runtime, with the possibility to store the changed
+configuration on the boot media.
+
+@section x86_bootloader_restrictions Restrictions
+
+Due to some BIOS and @a barebox restrictions the boot media must be
+prepared in some special way:
+
+@li @a barebox must be stored in the MBR (Master Boot Record) of the boot media.
+    Currently its not possible to store and boot it in one of the partition
+    sectors (to use it as a second stage loader). This is no eternal
+    restriction. It only needs further effort to add this feature.
+@li @a barebox currently cannot run a chained boot loader. Also, this is no
+    eternal restriction, only further effort needed.
+@li @a barebox comes with limited filesystem support. There is currently no
+    support for the most common and popular filesystems used in the *NIX world.
+    This restricts locations where to store a kernel and other runtime
+    information
+@li @a barebox must be stored to the first n sectors of the boot media. To ensure
+    this does not collide with partitions on the boot media, the first
+    partition must start at a sector behind the ones @a barebox occupies.
+@li @a barebox handles its runtime configuration in a special way: It stores it
+    in a binary way into some reserved sectors ("persistant storage").
+
+@section x86_bootloader_preparations Boot Preparations
+
+To store the @a barebox image to a boot media, it comes with the tool
+@p setupmbr in the directory @p scripts/setupmbr/ . To be able to use it on
+the boot media of your choice, some preparations are required:
+
+@subsection x86_bootloader_preparations_partition Keep Sectors free
+
+Build the @a barebox image and check its size. At least this amount of
+sectors must be kept free after the MBR prior the first partition. Do this
+simple calulation:
+
+	sectors = (\<size of barebox image\> + 511) / 512
+
+To be able to store the runtime configuration, further free sectors are
+required. Its up to you and your requirements, how large this persistant
+storage must be. If you need 16 kiB for this purpose, you need to keep
+additional 32 sectors free.
+
+For this example we are reserving 300 sectors for the @a barebox image and
+additionaly 32 sectors for the persistant storage. So, the first partition on
+the boot media must start at sector 333 or later.
+
+Run the @p fdisk tool to setup such a partition table:
+
+@verbatim
+[jb@host]~> fdisk /dev/sda
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders
+Units = cylinders of 1008 * 512 = 516096 bytes
+
+   Device Boot      Start         End      Blocks   Id  System
+@endverbatim
+
+Change the used units to @p sectors for easier handling.
+
+@verbatim
+Command (m for help): u
+Changing display/entry units to sectors
+
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders, total 409248 sectors
+Units = sectors of 1 * 512 = 512 bytes
+
+   Device Boot      Start         End      Blocks   Id  System
+@endverbatim
+
+Now its possible to create the first partition with the required offset:
+
+@verbatim
+Command (m for help): n
+Command action
+   e   extended
+   p   primary partition (1-4)
+p
+Partition number (1-4): 1
+First sector (63-409247, default 63): 333
+Last sector or +size or +sizeM or +sizeK (333-409247, default 409247): +18M
+Command (m for help): p
+
+Disk /dev/sda: 20.7 MB, 212680704 bytes
+16 heads, 63 sectors/track, 406 cylinders, total 409248 sectors
+Units = sectors of 1 * 512 = 512 bytes
+
+        Device Boot      Start         End      Blocks   Id  System
+/dev/sda                   333       35489       17578+  83  Linux
+@endverbatim
+
+That's all. Do whatever is required now with the new partition (formatting
+and populating the root filesystem for example) to make it useful.
+
+In the next step, @a barebox gets installed to this boot media:
+
+@verbatim
+[jb@host]~> scripts/setupmbr/setupmbr -s 32 -m ./barebox -d /dev/sda
+@endverbatim
+
+This command writes the @a barebox image file './barebox' onto the device
+@p /dev/sda.
+
+The @p -s option will keep the persistant storage sectors free and untouched
+and set flags in the MBR to forward its existance, size and location to
+@a barebox at runtime. @p setupmbr also does not change the partition table.
+
+The @a barebox image gets stored on the boot media like this:
+
+@verbatim
+sector 0   1             33                              333
+       |---|-------------|--------------- ~~~ ------------|--------------
+      MBR    persistant              barebox                 first
+              storage               main image              partition
+@endverbatim
+
+If the @p -s option is omitted, the "persistant storage" part simply does
+not exist:
+
+@verbatim
+sector 0   1                              333
+       |---|--------------- ~~~ ------------|--------------
+      MBR               barebox                 first
+                       main image              partition
+@endverbatim
+
+@note The @p setupmbr tool is also working on real image file than on device
+      nodes only. So, there is no restriction what kind of file will be
+      modified.
+*/
Index: barebox-2009.12.0/Doxyfile
===================================================================
--- barebox-2009.12.0.orig/Doxyfile
+++ barebox-2009.12.0/Doxyfile
@@ -484,7 +484,8 @@ INPUT                  = Documentation \
                          commands \
                          common \
                          board \
-                         lib
+                         lib \
+                         scripts/setupmbr
 
 # This tag can be used to specify the character encoding of the source files that
 # doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 02/14] Consider real and protected mode in the dump file
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 01/14] Add a tool to activate barebox as a boot loader on x86 architectures Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 03/14] Adding x86 usage documentation to the tree Juergen Beisert
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: consider_code_type.diff --]
[-- Type: text/plain, Size: 2019 bytes --]

On x86 'objdump' does not know which parts of the image are 16 bit code and
32 bit. As the default is 32 bit, it will output garbage from the 16 bit parts
(due to 16/32 bit ops are sharing the same opcodes).

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 Makefile |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

Index: barebox-2009.12.0/Makefile
===================================================================
--- barebox-2009.12.0.orig/Makefile
+++ barebox-2009.12.0/Makefile
@@ -643,7 +643,30 @@ endef
 
 barebox.bin: barebox
 	$(Q)$(OBJCOPY) -O binary barebox barebox.bin
+ifdef CONFIG_X86
+ifdef CONFIG_X86_HDBOOT
+	@echo "-------------------------------------------------" > barebox.S
+	@echo " * MBR content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .bootsector -mi8086 -d barebox >> barebox.S
+	@echo "-------------------------------------------------" >> barebox.S
+	@echo " * Boot loader content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .bootstrapping -mi8086 -d barebox >> barebox.S
+endif
+	@echo "-------------------------------------------------" >> barebox.S
+	@echo " * Regular Text content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .text -d barebox >> barebox.S
+	@echo "-------------------------------------------------" >> barebox.S
+	@echo " * Regular Data content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .data -d barebox >> barebox.S
+	@echo "-------------------------------------------------" >> barebox.S
+	@echo " * Commands content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .barebox_cmd -d barebox >> barebox.S
+	@echo "-------------------------------------------------" >> barebox.S
+	@echo " * Init Calls content" >> barebox.S
+	$(Q)$(OBJDUMP) -j .barebox_initcalls -d barebox >> barebox.S
+else
 	$(Q)$(OBJDUMP) -d barebox > barebox.S
+endif
 
 # barebox image
 barebox: $(barebox-lds) $(barebox-head) $(barebox-common) $(kallsyms.o) FORCE

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 03/14] Adding x86 usage documentation to the tree
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 01/14] Add a tool to activate barebox as a boot loader on x86 architectures Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 02/14] Consider real and protected mode in the dump file Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 04/14] Adding required architecture header files Juergen Beisert
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_x86_documentation.diff --]
[-- Type: text/plain, Size: 6236 bytes --]

Adding x86 usage documentation to the tree

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 Documentation/developers_manual.dox |    1 
 Documentation/users_manual.dox      |    1 
 arch/architecture.dox               |    1 
 arch/x86/mach-x86.dox               |  128 ++++++++++++++++++++++++++++++++++++
 4 files changed, 131 insertions(+)

Index: barebox-2009.12.0/arch/x86/mach-x86.dox
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/mach-x86.dox
@@ -0,0 +1,128 @@
+/* This document is intended to provide the developer with information
+ * how to integrate a new CPU (MACH) into this part of the barebox tree
+ */
+
+/** @page x86_runtime barebox on x86 at runtime
+
+@section mach_x86_memory_layout barebox's memory layout (BIOS based)
+
+@a barebox uses the following memory layout at runtime when it still depends
+on some kind of BIOS function:
+
+@verbatim
+     Addresses
+------------------------
+
+ seg:off     flat
+
+xxxx:xxxx 0x01xxxxxx    end of  barebox's malloc area
+    .        .
+xxxx:xxxx 0x01000000    start of barebox's malloc area
+    .          .
+    .          .        (used while loading a Linux kernel of type 'bzImage')
+    .          .
+xxxx:xxxx 0x00100000    start of extended memory and  malloc area
+    .          .
+    .          .	(the big hole)
+    .          .
+9000:ffff 0x0009ffff    end of expected real mode memory
+    .          .
+    .          .        (used while loading a Linux kernel of type 'bzImage')
+    .          .
+9000:0000 0x00090000    end of used lower real mode memory
+    .          .
+    .          .
+    .          .        Flat mode stack (about 32 kiB)
+    .          .        bss
+    .          .        Data
+    .          .        Text
+0000:7e00 0x00007e00	Real and flat mode barebox code
+0000:7c00 0x00007c00	MBR initial boot loader code
+0000:7a00 0x00007a00	location of the indirect sector (while booting only)
+			below: real mode stack
+@endverbatim
+
+@note The start address of 0x0000:7c000 is a fixed one, defined by the BIOS.
+So, for a BIOS based @a barebox this address can't be changed.
+
+While the @a barebox code is runnung in flat mode, all interrupts are disabled.
+But in the CPU only. All other interrupt settings are still valid. This is
+required to be able to call real mode code from inside @a barebox flat mode
+code. Thats why not the PIC is touched nor the IDT.
+
+@todo Add some notes about drive numbers used by the BIOS. They may change
+if one change orders in the BIOS setup. Drive orders and numbers may be
+different at BIOS runtime and Linux runtime! But these numbers are required
+at BIOS runtime for booting and the persistant environment storage.
+
+@attention Currently there is a 4 GiB limit for the disk sizes!
+
+@section mach_x86_image_layout barebox's image layout
+
+@a barebox's binary image layout
+
+@verbatim
+  Offset     Content
+
+ 0x?????
+    .        32 bit barebox code
+    .
+    .        16 bit bootstrap code, BIOS calling code
+ 0x00400
+ 0x003ff
+    .        indirect sector
+ 0x00200
+ 0x001ff
+    .        MBR
+ 0x00000
+@endverbatim
+
+The "indirect sector" is a free area in the image where the sector information
+gets stored when this image will be written to a boot media. This information
+is required to load all parts of the image from the boot media at runtime.
+
+The image gets installed in two ways onto the boot media, depending on the
+need for a persistant storage.
+
+@subsection mach_x86_drive_layout_wops barebox's boot media layout without persistant storage
+
+In this case @a barebox's persistant storage is anywhere:
+
+@verbatim
+  Sector     Content
+---------------------------
+    X        start of first partition
+    .
+    ?        end of the binary image
+    .        32 bit barebox code
+    2        16 bit bootstrap code, BIOS calling code
+    1        indirect sector
+    0        MBR, Partition table, boot code
+@endverbatim
+
+@subsection mach_x86_drive_layout_wps barebox's boot media layout with persistant storage
+
+@a barebox's persistant storage is part of the boot media (more
+space required in front of the first partition) and interferes with the
+boot loader image itself:
+
+@verbatim
+  Sector     Content
+---------------------------
+    X        start of first partition
+    .
+    n+?      end of the binary image
+    .        32 bit barebox code
+    n+2      16 bit bootstrap code, BIOS calling code
+    n+1      indirect sector
+    n        end of persistant environment storage
+    .
+    1        start of persistant environment storage
+    0        MBR, Partition table, boot code
+@endverbatim
+
+The information where the persistant storage is located is also stored into
+the MBR at specific locations by @p setupmbr. The @a barebox runtime will use
+it to load and store all environment relevant data.
+
+*/
Index: barebox-2009.12.0/arch/architecture.dox
===================================================================
--- barebox-2009.12.0.orig/arch/architecture.dox
+++ barebox-2009.12.0/arch/architecture.dox
@@ -88,6 +88,7 @@ TODO
 @li @subpage dev_bf_mach
 @li @subpage dev_ppc_mach
 @li @subpage dev_m68k_mach
+@li @subpage dev_x86_mach
 
 */
 
Index: barebox-2009.12.0/Documentation/users_manual.dox
===================================================================
--- barebox-2009.12.0.orig/Documentation/users_manual.dox
+++ barebox-2009.12.0/Documentation/users_manual.dox
@@ -10,5 +10,6 @@ work easier.
 @li @subpage readline_parser
 @li @subpage command_reference
 @li @subpage partitions
+@li @subpage x86_bootloader
 
 */
Index: barebox-2009.12.0/Documentation/developers_manual.dox
===================================================================
--- barebox-2009.12.0.orig/Documentation/developers_manual.dox
+++ barebox-2009.12.0/Documentation/developers_manual.dox
@@ -20,5 +20,6 @@ This part of the documentation is intend
 @li @subpage barebox_simul
 @li @subpage io_access_functions
 @li @subpage mcfv4e_MCDlib
+@li @subpage x86_runtime
 
 */

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 04/14] Adding required architecture header files
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (2 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 03/14] Adding x86 usage documentation to the tree Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 05/14] Bring in the first x86 specific code Juergen Beisert
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: x86_headers.diff --]
[-- Type: text/plain, Size: 23067 bytes --]

Add architecture header files. Some of these files are empty, they only must
exists to make the build system happy.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/include/asm/barebox.h     |   21 ++++++
 arch/x86/include/asm/barebox.lds.h |  113 +++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/bitops.h      |   32 ++++++++++
 arch/x86/include/asm/byteorder.h   |   30 +++++++++
 arch/x86/include/asm/common.h      |   29 +++++++++
 arch/x86/include/asm/elf.h         |   30 +++++++++
 arch/x86/include/asm/io.h          |   73 +++++++++++++++++++++++
 arch/x86/include/asm/modes.h       |   65 +++++++++++++++++++++
 arch/x86/include/asm/module.h      |   37 ++++++++++++
 arch/x86/include/asm/posix_types.h |   49 ++++++++++++++++
 arch/x86/include/asm/segment.h     |   43 ++++++++++++++
 arch/x86/include/asm/string.h      |   31 ++++++++++
 arch/x86/include/asm/syslib.h      |   29 +++++++++
 arch/x86/include/asm/types.h       |   44 ++++++++++++++
 14 files changed, 626 insertions(+)

Index: barebox-2009.12.0/arch/x86/include/asm/bitops.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/bitops.h
@@ -0,0 +1,32 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 bit operations
+ *
+ * This file is required only to make all sources happy including
+ * 'linux/bitops.h'
+ */
+
+#ifndef _ASM_X86_BITOPS_H_
+#define _ASM_X86_BITOPS_H_
+
+/* nothing special yet */
+
+#endif /* _ASM_X86_BITOPS_H_ */
Index: barebox-2009.12.0/arch/x86/include/asm/byteorder.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/byteorder.h
@@ -0,0 +1,30 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 endianess declaration
+ */
+
+#ifndef __ASM_X86_BYTEORDER_H
+#define __ASM_X86_BYTEORDER_H
+
+#include <asm/types.h>
+#include <linux/byteorder/little_endian.h>
+
+#endif
Index: barebox-2009.12.0/arch/x86/include/asm/common.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/common.h
@@ -0,0 +1,29 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 common declarations
+ */
+
+#ifndef _ASM_X86_COMMON_H_
+#define _ASM_X86_COMMON_H_
+
+/* Nothing exiting yet */
+
+#endif /* _ASM_X86_COMMON_H_ */
Index: barebox-2009.12.0/arch/x86/include/asm/elf.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/elf.h
@@ -0,0 +1,30 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 specific elf information
+ *
+ */
+
+#ifndef _ASM_X86_ELF_H
+#define _ASM_X86_ELF_H
+
+#define ELF_CLASS ELFCLASS32
+
+#endif /* _ASM_X86_ELF_H */
Index: barebox-2009.12.0/arch/x86/include/asm/io.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/io.h
@@ -0,0 +1,73 @@
+/*
+ * Mostly stolen from the linux kernel
+ */
+
+/**
+ * @file
+ * @brief x86 IO access functions
+ */
+
+#ifndef __ASM_X86_IO_H
+#define __ASM_X86_IO_H
+
+static inline void outb(unsigned char value, int port)
+{
+	asm volatile("outb %b0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outw(unsigned short value, int port)
+{
+	asm volatile("outw %w0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline void outl(unsigned long value, int port)
+{
+	asm volatile("outl %0, %w1" : : "a"(value), "Nd"(port));
+}
+
+static inline unsigned char inb(int port)
+{
+	unsigned char value;
+	asm volatile("inb %w1, %b0" : "=a"(value) : "Nd"(port));
+	return value;
+}
+
+static inline unsigned short inw(int port)
+{
+	unsigned short value;
+	asm volatile("inw %w1, %w0" : "=a"(value) : "Nd"(port));
+	return value;
+}
+
+static inline unsigned long inl(int port)
+{
+	unsigned long value;
+	asm volatile("inl %w1, %0" : "=a"(value) : "Nd"(port));
+	return value;
+}
+
+#define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void *addr) \
+ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+ :"m" (*(volatile type*)addr) barrier); return ret; }
+
+build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
+build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
+build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
+
+#define build_mmio_write(name, size, type, reg, barrier) \
+ static inline void name(type val, volatile void *addr) \
+ { asm volatile("mov" size " %0,%1": :reg (val), \
+ "m" (*(volatile type*)addr) barrier); }
+
+build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
+build_mmio_write(writew, "w", unsigned short, "r", :"memory")
+build_mmio_write(writel, "l", unsigned int, "r", :"memory")
+
+/* do a tiny io delay */
+static inline void io_delay(void)
+{
+	inb(0x80);
+}
+
+#endif	/* __ASM_X86_IO_H */
Index: barebox-2009.12.0/arch/x86/include/asm/posix_types.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/posix_types.h
@@ -0,0 +1,49 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 posix types
+ *
+ * Minimal set to make all the other header files copied from the Linxu kernel happy
+ */
+
+#ifndef _ASM_X86_POSIX_TYPES_H
+#define _ASM_X86_POSIX_TYPES_H
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_dev_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+typedef long long	__kernel_loff_t;
+
+#endif /* _ASM_X86_POSIX_TYPES_H */
Index: barebox-2009.12.0/arch/x86/include/asm/segment.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/segment.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _ASM_X86_SEGMENT_H
+#define _ASM_X86_SEGMENT_H
+
+#include <linux/compiler.h>
+
+/**
+ * @file
+ * @brief To be able to mark functions running in real _and_ flat mode
+ */
+
+/**
+ * Section for every program code needed to bring barebox from real mode
+ * to flat mode
+ */
+#define __bootcode	__section(.boot.text)
+
+/**
+ * Section for every data needed to bring barebox from real mode
+ * to flat mode
+ */
+#define __bootdata	__section(.boot.data)
+
+#endif /* _ASM_X86_SEGMENT_H */
Index: barebox-2009.12.0/arch/x86/include/asm/string.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/string.h
@@ -0,0 +1,31 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 specific string optimizations
+ *
+ * Thanks to the Linux kernel here we can add many micro optimized string
+ * functions. But currently it makes no sense, to do so.
+ */
+#ifndef __ASM_X86_STRING_H
+#define __ASM_X86_STRING_H
+
+/* nothing special yet */
+
+#endif
Index: barebox-2009.12.0/arch/x86/include/asm/syslib.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/syslib.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+extern unsigned int x86_uart_read(unsigned long, unsigned char);
+extern void x86_uart_write(unsigned int, unsigned long, unsigned char);
+
+#ifdef CONFIG_X86_BIOS_BRINGUP
+
+extern int bios_disk_rw_int13_extensions(int, int, void*) __attribute__((regparm(3)));
+extern uint16_t bios_get_memsize(void);
+
+#endif
Index: barebox-2009.12.0/arch/x86/include/asm/types.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/types.h
@@ -0,0 +1,44 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ASM_X86_TYPES_H
+#define __ASM_X86_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+
+typedef unsigned char u8;
+
+typedef unsigned short u16;
+
+typedef unsigned int u32;
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_X86_TYPES_H */
Index: barebox-2009.12.0/arch/x86/include/asm/barebox.lds.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/barebox.lds.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Adapt linker script content in accordance to Kconfig settings
+ */
+
+#define INITCALLS			\
+	KEEP(*(.initcall.0))			\
+	KEEP(*(.initcall.1))			\
+	KEEP(*(.initcall.2))			\
+	KEEP(*(.initcall.3))			\
+	KEEP(*(.initcall.4))			\
+	KEEP(*(.initcall.5))			\
+	KEEP(*(.initcall.6))			\
+	KEEP(*(.initcall.7))
+
+#define BAREBOX_CMDS	KEEP(*(SORT_BY_NAME(.barebox_cmd*)))
+
+#define BAREBOX_SYMS	KEEP(*(__usymtab))
+
+/**
+ * Area in the MBR of the barebox basic boot code. This offset must be in
+ * accordance to the 'indirect_sector_lba' label.
+ */
+#define PATCH_AREA 400
+
+/**
+ * Offset where to store the boot drive number (BIOS number, 1 byte)
+ */
+#define PATCH_AREA_BOOT_DEV 16
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * It points to an LBA number (8 bytes) and defines the first sector of this
+ * storage on disk.
+ */
+#define PATCH_AREA_PERS_START 20
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * It points to a short number (2 bytes) and defines the sector count of this
+ * storage on disk.
+ */
+#define PATCH_AREA_PERS_SIZE 28
+
+/**
+ * Offset where to store information about the persistant environment storage
+ * drive number (BIOS number, 1 byte)
+ */
+#define PATCH_AREA_PERS_DRIVE 30
+
+/**
+ * Mark the persistant environment as not used
+ */
+#define PATCH_AREA_PERS_SIZE_UNUSED 0x000
+
+/**
+ * Mark a DAPS as unused/invalid
+ */
+#define MARK_DAPS_INVALID 0x0000
+
+/**
+ * Offset of the partition table in an MBR
+ */
+#define OFFSET_OF_PARTITION_TABLE 446
+
+/**
+ * Offset of the signature in an MBR
+ */
+#define OFFSET_OF_SIGNATURE 510
+
+/**
+ * Area where to store indirect sector to loop through. Keep this value
+ * in accordance to the 'indirect_area' label. Note: .
+ *
+ * @attention These addresses are real mode ones (seg:offset)
+ */
+#define INDIRECT_AREA 0x7A00
+#define INDIRECT_SEGMENT 0x0000
+
+/**
+ * Area where to load sectors from disk to. They should start after the
+ * MBR area and must be in accordance to the offset of the '.bootstrapping'
+ * section in the linker file.
+ *
+ * @attention The address must be a multiple of 512.
+ */
+#define LOAD_AREA 0x7e00
+#define LOAD_SEGMENT 0x0000
+
+/**
+ * Size of one sector.
+ */
+#define SECTOR_SIZE 512
Index: barebox-2009.12.0/arch/x86/include/asm/barebox.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/barebox.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* nothing special yet */
Index: barebox-2009.12.0/arch/x86/include/asm/modes.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/modes.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Declarations to bring some light in the real/protected/flat mode darkness
+ */
+#ifndef _ASM_X86_MODES_H
+#define _ASM_X86_MODES_H
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+extern uint64_t gdt[];
+extern unsigned gdt_size;
+
+#endif
+
+/** to simplify GDT entry generation */
+#define GDT_ENTRY(flags, base, limit)			\
+	((((base)  & 0xff000000ULL) << (56-24)) |	\
+	 (((flags) & 0x0000f0ffULL) << 40) |		\
+	 (((limit) & 0x000f0000ULL) << (48-16)) |	\
+	 (((base)  & 0x00ffffffULL) << 16) |		\
+	 (((limit) & 0x0000ffffULL)))
+
+/** 32 bit barebox text */
+#define GDT_ENTRY_BOOT_CS	2
+#define __BOOT_CS		(GDT_ENTRY_BOOT_CS * 8)
+
+/** 32 bit barebox data */
+#define GDT_ENTRY_BOOT_DS	3
+#define __BOOT_DS		(GDT_ENTRY_BOOT_DS * 8)
+
+/** 16 bit barebox text */
+#define GDT_ENTRY_REAL_CS	4
+#define __REAL_CS		(GDT_ENTRY_REAL_CS * 8)
+
+/** 16 bit barebox data */
+#define GDT_ENTRY_REAL_DS	5
+#define __REAL_DS		(GDT_ENTRY_REAL_DS * 8)
+
+/** Something to make others happy */
+#define GDT_ENTRY_BOOT_TSS	6
+#define __BOOT_TSS		(GDT_ENTRY_BOOT_TSS * 8)
+
+#endif /* _ASM_X86_MODES_H */
Index: barebox-2009.12.0/arch/x86/include/asm/module.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/include/asm/module.h
@@ -0,0 +1,37 @@
+/*
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 module support
+ *
+ */
+
+#ifndef _ASM_X86_MODULE_H_
+#define _ASM_X86_MODULE_H_
+
+/** currently nothing special */
+struct mod_arch_specific
+{
+        int foo;
+};
+
+#define Elf_Shdr        Elf32_Shdr
+#define Elf_Ehdr        Elf32_Ehdr
+
+#endif /* _ASM_X86_MODULE_H_ */

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 05/14] Bring in the first x86 specific code
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (3 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 04/14] Adding required architecture header files Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 06/14] Add some generic functions to make x86 work Juergen Beisert
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_mach_code.diff --]
[-- Type: text/plain, Size: 4326 bytes --]

Add some generic required code to make barebox work on x86.
Note: Resetting the CPU is unfinished yet. I need some ideas how to reset
this kind of architecture gracefully.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/mach-i386/Kconfig   |   29 +++++++++++++++++++++++++++++
 arch/x86/mach-i386/Makefile  |    2 ++
 arch/x86/mach-i386/generic.c |   38 ++++++++++++++++++++++++++++++++++++++
 arch/x86/mach-i386/reset.c   |   34 ++++++++++++++++++++++++++++++++++
 4 files changed, 103 insertions(+)

Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/Kconfig
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/Kconfig
@@ -0,0 +1,29 @@
+
+menu "Board specific settings       "
+
+if X86_BOOTLOADER
+
+config X86_GENERIC_HAS_ISA
+	bool "ISA support"
+	help
+	  Say Y here if the target supports a ISA bus
+
+config X86_GENERIC_HAS_PCI
+	bool "PCI support"
+	select HAS_PCI
+	help
+	  Say Y here if the target supports a PCI bus
+
+config X86_GENERIC_HAS_VIDEO
+	bool "video support"
+	help
+	  Say Y here if the target supports a video output
+
+config X86_GENERIC_HAS_USB
+	bool "USB support"
+	help
+	  Say Y here if the target supports a USB interface
+
+endif
+
+endmenu
Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/Makefile
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/Makefile
@@ -0,0 +1,2 @@
+obj-y += generic.o
+obj-y += reset.o
Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/generic.c
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/generic.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief x86 Architecture Initialization routines
+ */
+
+#include <asm/io.h>
+
+/** to work with the 8250 UART driver implementation we need this function */
+unsigned int x86_uart_read(unsigned long base, unsigned char reg_idx)
+{
+	return inb(base + reg_idx);
+}
+
+/** to work with the 8250 UART driver implementation we need this function */
+void x86_uart_write(unsigned int val, unsigned long base, unsigned char reg_idx)
+{
+	outb(val, base + reg_idx);
+}
Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/reset.c
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/reset.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Resetting an x86 CPU
+ */
+
+#include <common.h>
+
+void reset_cpu(ulong addr)
+{
+	/** How to reset the machine? */
+	while(1)
+		;
+}
+EXPORT_SYMBOL(reset_cpu);

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 06/14] Add some generic functions to make x86 work
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (4 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 05/14] Bring in the first x86 specific code Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 07/14] Add functions to be able to boot with BIOSs help Juergen Beisert
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_lib_code.diff --]
[-- Type: text/plain, Size: 17606 bytes --]

Add some generic functions to make barebox work on x86.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/lib/Makefile      |    7 +
 arch/x86/lib/barebox.lds.S |  194 +++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/lib/gdt.c         |   55 ++++++++++++
 arch/x86/lib/memory.c      |   67 +++++++++++++++
 arch/x86/lib/memory16.S    |   73 ++++++++++++++++
 arch/x86/lib/traveler.S    |  183 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 579 insertions(+)

Index: barebox-2009.12.0/arch/x86/lib/Makefile
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/Makefile
@@ -0,0 +1,7 @@
+extra-$(CONFIG_GENERIC_LINKER_SCRIPT) += barebox.lds
+obj-y += memory.o
+obj-y += gdt.o
+
+# needed, when running via a 16 bit BIOS
+obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o
+obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o
Index: barebox-2009.12.0/arch/x86/lib/barebox.lds.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/barebox.lds.S
@@ -0,0 +1,194 @@
+/*
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#undef i386
+#include <asm/barebox.lds.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+MEMORY
+{
+	mbr(rwx): ORIGIN = TEXT_BASE, LENGTH = 2 * SECTOR_SIZE
+	barebox (rwx) : ORIGIN = TEXT_BASE + SECTOR_SIZE, LENGTH = (256 * 1024 * 1024)
+}
+
+SECTIONS
+{
+#ifdef CONFIG_X86_HDBOOT
+
+	.ramlayout : {
+		boot_stack = INDIRECT_AREA;
+		indirect_area = INDIRECT_AREA;
+	}
+	/* describing the main boot sector */
+	.bootsector : AT (0) {
+		*(.boot_start)
+
+		. = 0x00b;
+		/*
+		 * Maybe later on occupied by a "BIOS parameter block". So,
+		 * keep it free from code.
+		 * - BytesPerSector dw@0x000B
+		 * - SectorsPerCluster db@0x000D
+		 * - ReservedSectors dw@0x000E
+		 * - FatCopies db@0x0010
+		 * - RootDirEntries dw@0x0011
+		 * - NumSectors dw@0x0013
+		 * - MediaType db@0x0015
+		 * - SectorsPerFAT dw@0x0016
+		 * - SectorsPerTrack dw@0x0018
+		 * - NumberOfHeads dw@0x001A
+		 * - HiddenSectors dd@0x001C
+		 * - SectorsBig dd@0x0020
+		 */
+		LONG(0);
+
+		. = 0x024;
+		*(.boot_code)
+		*(.boot_data)
+
+		/*
+		 * embed one "Disk Address Packet Structure" into the boot sector
+		 * This DAPS points to the 'indirect' sector to give the boot code
+		 * an idea what and where to load. Its content must be adapted
+		 * to the system it should run on, so, this structure must be
+		 * located at a well known offset.
+		 */
+		. = PATCH_AREA;
+		indirect_sector_lba = .;
+		SHORT(0x0010);		/* size of this structure */
+		SHORT(0x0001);		/* one sector */
+		SHORT(indirect_area);	/* where to store: offset */
+		SHORT(0x0000);		/* where to store: segment */
+		/* the following values are filled by the installer */
+		LONG(0x00000000);	/* LBA start lower */
+		LONG(0x00000000);	/* LBA start upper */
+
+		/* boot disk number used by upper layers */
+		. = PATCH_AREA + PATCH_AREA_BOOT_DEV;
+		boot_disk = .;
+		BYTE(0x00);		/* boot disk number (provided by the BIOS)
+
+		/* information about the persistant environment storage */
+		. = PATCH_AREA + PATCH_AREA_PERS_START;
+		pers_env_storage = .;
+		LONG(0x00000000);	/* LBA start lower */
+		LONG(0x00000000);	/* LBA start upper */
+
+		. = PATCH_AREA + PATCH_AREA_PERS_SIZE;
+		pers_env_size = .;
+		SHORT(PATCH_AREA_PERS_SIZE_UNUSED);	/* size of this area in sectors */
+
+		. = PATCH_AREA + PATCH_AREA_PERS_DRIVE;
+		pers_env_drive = .;
+		BYTE(0x00);		/* used drive */
+
+		/* partition table area (fixed location) */
+		. = OFFSET_OF_PARTITION_TABLE;
+		/* create an empty one */
+		LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+		LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+		LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+		LONG(0x00000000); LONG(0x00000000); LONG(0x00000000); LONG(0x00000000);
+
+		/* boot sector signature */
+		. = OFFSET_OF_SIGNATURE;
+		BYTE(0x55);
+		BYTE(0xAA);
+		/* end of the first sector */
+
+		/*
+		 * The indirect sector starts here
+		 */
+		. = SECTOR_SIZE;
+		BYTE(MARK_DAPS_INVALID);	/* mark the first entry invalid */
+		BYTE(0x00);
+		. = SECTOR_SIZE + 496;
+		BYTE(MARK_DAPS_INVALID);	/* mark the last entry invalid */
+		BYTE(0x00);
+		. = SECTOR_SIZE + 508;
+		LONG(0x00000000);	/* LBA start upper */
+	} > mbr
+
+	/* some real mode bootstrapping */
+	.bootstrapping : AT ( LOADADDR(.bootsector) + SIZEOF(.bootsector) ) {
+		*(.boot.head)
+		*(.boot.text*)
+		*(.boot.rodata*)
+		*(.boot.data*)
+		. = ALIGN(4);
+	} > barebox
+#endif
+
+	/* the main barebox part (32 bit) */
+	.text : AT ( LOADADDR(.bootstrapping) + SIZEOF(.bootstrapping) ) {
+		/* do not align here! It may fails with the LOADADDR! */
+		_stext = .;
+		*(.text_entry*)
+		*(.text_bare_init*)
+		*(.text*)
+		. = ALIGN(4);
+		*(.rodata*)
+		. = ALIGN(4);
+		_etext = .;			/* End of text and rodata section */
+	} > barebox
+
+	.data : AT ( LOADADDR(.text) + SIZEOF(.text) ) {
+		*(.data*)
+		. = ALIGN(4);
+	} > barebox
+
+	.got : AT ( LOADADDR(.data) + SIZEOF (.data) ) {
+		*(.got*)
+		. = ALIGN(4);
+	} > barebox
+
+	.barebox_cmd : AT ( LOADADDR(.got) + SIZEOF (.got) ) {
+		__barebox_cmd_start = .;
+		BAREBOX_CMDS
+		__barebox_cmd_end = .;
+		. = ALIGN(4);
+	} > barebox
+
+	.barebox_initcalls : AT ( LOADADDR(.barebox_cmd) + SIZEOF (.barebox_cmd) ) {
+		__barebox_initcalls_start = .;
+		INITCALLS
+		__barebox_initcalls_end = .;
+		. = ALIGN(4);
+	} > barebox
+
+	.__usymtab : AT ( LOADADDR(.barebox_initcalls) + SIZEOF (.barebox_initcalls) ) {
+		__usymtab_start = .;
+		BAREBOX_SYMS
+		__usymtab_end = .;
+		. = ALIGN(4);
+	} > barebox
+
+	.bss : {
+		__bss_start = .;
+		*(.bss*);
+		*( COMMON )
+		__bss_end = .;
+		_end = .;
+	} > barebox
+}
Index: barebox-2009.12.0/arch/x86/lib/gdt.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/gdt.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Definition of the Global Descriptor Table
+ */
+
+#include <types.h>
+#include <asm/modes.h>
+#include <asm/segment.h>
+
+/**
+ * The 'Global Descriptor Table' used in barebox
+ *
+ * Note: This table must reachable by real and flat mode code
+ */
+uint64_t gdt[] __attribute__((aligned(16))) __bootdata = {
+	/* CS: code, read/execute, 4 GB, base 0 */
+	[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+	/* DS: data, read/write, 4 GB, base 0 */
+	[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+	/* CS: for real mode calls */
+	[GDT_ENTRY_REAL_CS] = GDT_ENTRY(0x009E, 0, 0x0ffff),
+	/* DS: for real mode calls */
+	[GDT_ENTRY_REAL_DS] = GDT_ENTRY(0x0092, 0, 0x0ffff),
+	/* TSS: 32-bit tss, 104 bytes, base 4096 */
+	/* We only have a TSS here to keep Intel VT happy;
+	   we don't actually use it for anything. */
+	[GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
+};
+
+/**
+ * Size of the GDT must be known to load it
+ *
+ * Note: This varibale must reachable by real and flat mode code
+ */
+unsigned gdt_size __bootdata = sizeof(gdt);
Index: barebox-2009.12.0/arch/x86/lib/memory.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/memory.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Memory management
+ */
+
+#include <init.h>
+#include <stdio.h>
+#include <mem_malloc.h>
+#include <asm/syslib.h>
+#include <asm-generic/memory_layout.h>
+
+/**
+ * Handling of free memory
+ *
+ * Topics:
+ * - areas used by BIOS code
+ * - The 0xa0000... 0xfffff hole
+ * - memory above 0x100000
+ */
+
+static int x86_mem_malloc_init(void)
+{
+#ifdef CONFIG_MEMORY_LAYOUT_DEFAULT
+	unsigned long memory_size;
+
+	memory_size = bios_get_memsize();
+	memory_size <<= 10;	/* BIOS reports in kiB */
+
+	/*
+	 * We do not want to conflict with the kernel. So, we keep the
+	 * area from 0x100000 ... 0xFFFFFF free from usage
+	 */
+	if (memory_size >= (15 * 1024 * 1024 + MALLOC_SIZE))
+		mem_malloc_init((void*)(16 * 1024 * 1024),
+				(void*)(16 * 1024 * 1024) + MALLOC_SIZE);
+	else
+		return -1;
+#else
+	mem_malloc_init((void *)MALLOC_BASE,
+			(void *)(MALLOC_BASE + MALLOC_SIZE));
+#endif
+	return 0;
+}
+
+core_initcall(x86_mem_malloc_init);
Index: barebox-2009.12.0/arch/x86/lib/traveler.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/traveler.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Switch from the flat mode world into the real mode world and vice versa
+ *
+ * Note: These functions are *called* and return in a different operating mode
+ */
+
+/**
+ * @fn void real_to_prot(void)
+ * @brief Switch from temp. real mode back to flat mode
+ *
+ * Called from a 32 bit flat mode segment and returns into a 16 bit segment
+ */
+
+/**
+ * @fn void prot_to_real(void)
+ * @brief Switch from flat mode to real mode
+ *
+ * Called from a 16 bit real mode segment and returns into a 32 bit segment
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <asm/modes.h>
+
+	.file "walkyrie.S"
+
+/* keep the current flat mode stack pointer, while playing in real mode */
+	.section .boot.data.protstack
+	.code32
+protstack: .long 4
+/* temp. store */
+return_addr: .long 4
+
+
+	.section .boot.text.real_to_prot, "ax"
+	.code16
+	.globl	real_to_prot
+	.type	real_to_prot, @function
+
+/* Note: This routine should not change any other standard registers than eax */
+real_to_prot:
+	/*
+	 * Always disable the interrupts, when returning to flat mode
+	 */
+	cli
+
+	/* turn on protected mode */
+	movl %cr0, %eax
+	orl $0x00000001, %eax
+	movl %eax, %cr0
+
+	/* jump to relocation, flush prefetch queue, and reload %cs */
+	DATA32 ljmp $__BOOT_CS, $return_to_flatmode
+
+/* ----------------------------------------------------------------------- */
+	.section .boot.text.return_to_flatmode, "ax"
+	.type return_to_flatmode, @function
+	.code32
+
+return_to_flatmode:
+	/* reload other segment registers */
+	movw $__BOOT_DS, %ax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %fs
+	movw %ax, %gs
+	movw %ax, %ss
+
+	/* move the return address from the real mode to the flat mode stack */
+	movl (%esp), %eax
+	movl %eax, return_addr
+
+	/* setup again the flat mode stack */
+	movl protstack, %eax
+	movl %eax, %esp
+	movl %eax, %ebp
+
+	movl return_addr, %eax
+	movl %eax, (%esp)
+
+	/* flag we returned happy here */
+	xorl %eax, %eax
+	ret
+
+	.size real_to_prot, .-real_to_prot
+
+/* ------------------------------------------------------------------------ */
+
+/* Note: This routine should not change any other standard registers than eax */
+
+	.section .boot.text.prot_to_real, "ax"
+	.globl prot_to_real
+	.type prot_to_real, @function
+	.extern boot_stack
+	.code32
+
+prot_to_real:
+	/* save the protected mode stack */
+	movl %esp, %eax
+	movl %eax, protstack
+
+	/* prepare the real mode stack */
+	/* - address to call to the top of this stack */
+	movl (%esp), %eax
+	movl %eax, boot_stack - 4
+
+	/* - the stack itself */
+	movl $boot_stack - 4, %eax
+	movl %eax, %esp
+	movl %eax, %ebp
+
+	/* prepare segments limits to 16 bit */
+	movw $__REAL_DS, %ax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %fs
+	movw %ax, %gs
+	movw %ax, %ss
+
+	/* at last, also limit the code segment to 16 bit */
+	ljmp $__REAL_CS, $return_to_realmode
+
+/* ----------------------------------------------------------------------- */
+
+	.section .boot.text.return_to_realmode, "ax"
+return_to_realmode:
+	.code16
+
+	/* disable protected mode */
+	movl %cr0, %eax
+	andl $(~0x00000001), %eax
+	movl %eax, %cr0
+
+	/*
+	 * all the protected mode settings are still cached in the CPU.
+	 * Refresh them by re-loading all registers in realmode
+	 * Start with the CS, continue with the data registers
+	 */
+	ljmp $0, $enter_realmode
+
+enter_realmode:
+	xorl %eax, %eax
+	movw %ax, %ds
+	movw %ax, %es
+	movw %ax, %fs
+	movw %ax, %gs
+	movw %ax, %ss
+	/*
+	 * back in plain real mode now, we can play again with the BIOS
+	 */
+
+	/* restore interrupts */
+	sti
+
+	/* return on realmode stack! */
+	DATA32 ret
+
+	.size prot_to_real, .-prot_to_real
+
+#endif
Index: barebox-2009.12.0/arch/x86/lib/memory16.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/memory16.S
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Query the memory layout information from the BIOS
+ *
+ * Note: This function is running in flat and real mode. Due to some
+ * other restrictions it must running from an address space below 0x10000
+ */
+
+/**
+ * @fn unsigned short bios_get_memsize(void)
+ * @brief Does a BIOS call "INT 15H, AH=88H" to get extended memory size
+ * @return Extended memory size in KB
+ *
+ * @note This call is limited to 64 MiB. So, if the system provides more than
+ * 64 MiB of memory, still 64 MiB are reported.
+ *
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+	.section .boot.text.bios_get_memsize, "ax"
+	.code32
+	.globl bios_get_memsize
+	.type bios_get_memsize, @function
+
+	.extern prot_to_real
+
+bios_get_memsize:
+
+	pushl %ebp
+
+	call prot_to_real	/* enter real mode */
+	.code16
+
+	movb $0x88, %ah
+	int $0x15
+
+	movw %ax, %dx
+
+	DATA32	call real_to_prot
+
+	.code32
+
+	movw %dx, %ax
+
+	popl %ebp
+	ret
+
+	.size bios_get_memsize, .-bios_get_memsize
+
+#endif

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 07/14] Add functions to be able to boot with BIOSs help
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (5 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 06/14] Add some generic functions to make x86 work Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 08/14] Add a generic PC platform Juergen Beisert
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_boot_code.diff --]
[-- Type: text/plain, Size: 27875 bytes --]

These functions are special: They are running in the 16 bit real mode world
to bring up barebox on an x86 box.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/boot/Kconfig         |   20 ++++
 arch/x86/boot/Makefile        |   13 ++
 arch/x86/boot/a20.c           |  170 ++++++++++++++++++++++++++++++++++++
 arch/x86/boot/bioscall.S      |   99 +++++++++++++++++++++
 arch/x86/boot/boot.h          |  193 ++++++++++++++++++++++++++++++++++++++++++
 arch/x86/boot/boot_hdisk.S    |  176 ++++++++++++++++++++++++++++++++++++++
 arch/x86/boot/boot_main.S     |   58 ++++++++++++
 arch/x86/boot/main_entry.c    |   44 +++++++++
 arch/x86/boot/pmjump.S        |   89 +++++++++++++++++++
 arch/x86/boot/prepare_uboot.c |   86 ++++++++++++++++++
 arch/x86/boot/regs.c          |   34 +++++++
 arch/x86/boot/tty.c           |   45 +++++++++
 12 files changed, 1027 insertions(+)

Index: barebox-2009.12.0/arch/x86/boot/Kconfig
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/Kconfig
@@ -0,0 +1,20 @@
+if X86_BIOS_BRINGUP
+
+menu "BIOS boot source              "
+
+config X86_HDBOOT
+	bool "HD boot"
+	help
+	  Add code to boot from harddisk
+
+config X86_VESA
+	bool
+	default y if X86_GENERIC_HAS_VIDEO
+
+config X86_VGA
+	bool
+	default y if X86_GENERIC_HAS_VIDEO
+
+endmenu
+
+endif
Index: barebox-2009.12.0/arch/x86/boot/Makefile
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/Makefile
@@ -0,0 +1,13 @@
+
+CPPFLAGS += -D__I386__ -fno-strict-aliasing -m32 -g -Os -march=i386 \
+	-mregparm=3 -fno-strict-aliasing -fomit-frame-pointer -ffreestanding \
+	-fno-toplevel-reorder -fno-unit-at-a-time -fno-stack-protector \
+	-mpreferred-stack-boundary=2
+
+obj-$(CONFIG_X86_HDBOOT)	+= boot_main.o boot_hdisk.o
+
+obj-$(CONFIG_X86_BIOS_BRINGUP)	+= prepare_uboot.o a20.o bioscall.o regs.o tty.o pmjump.o main_entry.o
+
+obj-$(CONFIG_X86_VESA) += console_vesa.o
+obj-$(CONFIG_X86_VGA) += console_vga.o
+obj-$(CONFIG_X86_SERIAL) += console_serial.o
Index: barebox-2009.12.0/arch/x86/boot/a20.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/a20.c
@@ -0,0 +1,170 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Enable A20 gate (return -1 on failure)
+ */
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include "boot.h"
+
+#define MAX_8042_LOOPS	100000
+#define MAX_8042_FF	32
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+static int __bootcode empty_8042(void)
+{
+	u8 status;
+	int loops = MAX_8042_LOOPS;
+	int ffs   = MAX_8042_FF;
+
+	while (loops--) {
+		io_delay();
+
+		status = inb(0x64);
+		if (status == 0xff) {
+			/* FF is a plausible, but very unlikely status */
+			if (!--ffs)
+				return -1; /* Assume no KBC present */
+		}
+		if (status & 1) {
+			/* Read and discard input data */
+			io_delay();
+			(void)inb(0x60);
+		} else if (!(status & 2)) {
+			/* Buffers empty, finished! */
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/* Returns nonzero if the A20 line is enabled.  The memory address
+   used as a test is the int $0x80 vector, which should be safe. */
+
+#define A20_TEST_ADDR	(4*0x80)
+#define A20_TEST_SHORT  32
+#define A20_TEST_LONG	2097152	/* 2^21 */
+
+static int __bootcode a20_test(int loops)
+{
+	int ok = 0;
+	int saved, ctr;
+
+	set_fs(0x0000);
+	set_gs(0xffff);
+
+	saved = ctr = rdfs32(A20_TEST_ADDR);
+
+	while (loops--) {
+		wrfs32(++ctr, A20_TEST_ADDR);
+		io_delay();	/* Serialize and make delay constant */
+		ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;
+		if (ok)
+			break;
+	}
+
+	wrfs32(saved, A20_TEST_ADDR);
+	return ok;
+}
+
+/* Quick test to see if A20 is already enabled */
+static int __bootcode a20_test_short(void)
+{
+	return a20_test(A20_TEST_SHORT);
+}
+
+/* Longer test that actually waits for A20 to come on line; this
+   is useful when dealing with the KBC or other slow external circuitry. */
+static int __bootcode a20_test_long(void)
+{
+	return a20_test(A20_TEST_LONG);
+}
+
+static void __bootcode enable_a20_bios(void)
+{
+	struct biosregs ireg;
+
+	initregs(&ireg);
+	ireg.ax = 0x2401;
+	intcall(0x15, &ireg, NULL);
+}
+
+static void __bootcode enable_a20_kbc(void)
+{
+	empty_8042();
+
+	outb(0xd1, 0x64);	/* Command write */
+	empty_8042();
+
+	outb(0xdf, 0x60);	/* A20 on */
+	empty_8042();
+
+	outb(0xff, 0x64);	/* Null command, but UHCI wants it */
+	empty_8042();
+}
+
+static void __bootcode enable_a20_fast(void)
+{
+	u8 port_a;
+
+	port_a = inb(0x92);	/* Configuration port A */
+	port_a |=  0x02;	/* Enable A20 */
+	port_a &= ~0x01;	/* Do not reset machine */
+	outb(port_a, 0x92);
+}
+
+/*
+ * Actual routine to enable A20; return 0 on ok, -1 on failure
+ */
+
+#define A20_ENABLE_LOOPS 255	/* Number of times to try */
+
+int __bootcode enable_a20(void)
+{
+       int loops = A20_ENABLE_LOOPS;
+       int kbc_err;
+
+       while (loops--) {
+	       /* First, check to see if A20 is already enabled
+		  (legacy free, etc.) */
+	       if (a20_test_short())
+		       return 0;
+
+	       /* Next, try the BIOS (INT 0x15, AX=0x2401) */
+	       enable_a20_bios();
+	       if (a20_test_short())
+		       return 0;
+
+	       /* Try enabling A20 through the keyboard controller */
+	       kbc_err = empty_8042();
+
+	       if (a20_test_short())
+		       return 0; /* BIOS worked, but with delayed reaction */
+
+	       if (!kbc_err) {
+		       enable_a20_kbc();
+		       if (a20_test_long())
+			       return 0;
+	       }
+
+	       /* Finally, try enabling the "fast A20 gate" */
+	       enable_a20_fast();
+	       if (a20_test_long())
+		       return 0;
+       }
+
+       return -1;
+}
Index: barebox-2009.12.0/arch/x86/boot/bioscall.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/bioscall.S
@@ -0,0 +1,99 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * "Glove box" for BIOS calls.  Avoids the constant problems with BIOSes
+ * touching registers they shouldn't be.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+	.file	"bioscall.S"
+	.code16
+	.section .boot.text.intcall, "ax"
+
+	.globl	intcall
+	.type	intcall, @function
+intcall:
+	/* Self-modify the INT instruction.  Ugly, but works. */
+	cmpb	%al, 3f
+	je	1f
+	movb	%al, 3f
+	jmp	1f		/* Synchronize pipeline */
+1:
+	/* Save state */
+	pushfl
+	pushw	%fs
+	pushw	%gs
+	pushal
+
+	/* Copy input state to stack frame */
+	subw	$44, %sp
+	movw	%dx, %si
+	movw	%sp, %di
+	movw	$11, %cx
+	rep; movsd
+
+	/* Pop full state from the stack */
+	popal
+	popw	%gs
+	popw	%fs
+	popw	%es
+	popw	%ds
+	popfl
+
+	/* Actual INT */
+	.byte	0xcd		/* INT opcode */
+3:	.byte	0
+
+	/* Push full state to the stack */
+	pushfl
+	pushw	%ds
+	pushw	%es
+	pushw	%fs
+	pushw	%gs
+	pushal
+
+	/* Re-establish C environment invariants */
+	cld
+	movzwl	%sp, %esp
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+
+	/* Copy output state from stack frame */
+	movw	68(%esp), %di	/* Original %cx == 3rd argument */
+	andw	%di, %di
+	jz	4f
+	movw	%sp, %si
+	movw	$11, %cx
+	rep; movsd
+4:	addw	$44, %sp
+
+	/* Restore state and return */
+	popal
+	popw	%gs
+	popw	%fs
+	popfl
+	retl
+	.size	intcall, .-intcall
+
+/* ------------------------------------------------------------------------ */
+	.code16
+	.section .boot.text.die, "ax"
+
+	.globl	die
+	.type	die, @function
+die:
+        hlt
+        jmp     die
+	.size	die, .-die
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
Index: barebox-2009.12.0/arch/x86/boot/boot.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/boot.h
@@ -0,0 +1,193 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Main declarations for the real mode code
+ */
+
+#ifndef BOOT_BOOT_H
+#define BOOT_BOOT_H
+
+#define STACK_SIZE	512	/* Minimum number of bytes for stack */
+
+/** Carry flag */
+#define X86_EFLAGS_CF	0x00000001
+
+/** PE flag */
+#define X86_CR0_PE      0x00000001
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+/* we are still in real mode here! */
+#define THIS_IS_REALMODE_CODE asm(".code16gcc");
+
+struct biosregs {
+	union {
+		struct {
+			uint32_t edi;
+			uint32_t esi;
+			uint32_t ebp;
+			uint32_t _esp;
+			uint32_t ebx;
+			uint32_t edx;
+			uint32_t ecx;
+			uint32_t eax;
+			uint32_t _fsgs;
+			uint32_t _dses;
+			uint32_t eflags;
+		};
+		struct {
+			uint16_t di, hdi;
+			uint16_t si, hsi;
+			uint16_t bp, hbp;
+			uint16_t _sp, _hsp;
+			uint16_t bx, hbx;
+			uint16_t dx, hdx;
+			uint16_t cx, hcx;
+			uint16_t ax, hax;
+			uint16_t gs, fs;
+			uint16_t es, ds;
+			uint16_t flags, hflags;
+		};
+		struct {
+			uint8_t dil, dih, edi2, edi3;
+			uint8_t sil, sih, esi2, esi3;
+			uint8_t bpl, bph, ebp2, ebp3;
+			uint8_t _spl, _sph, _esp2, _esp3;
+			uint8_t bl, bh, ebx2, ebx3;
+			uint8_t dl, dh, edx2, edx3;
+			uint8_t cl, ch, ecx2, ecx3;
+			uint8_t al, ah, eax2, eax3;
+		};
+	};
+};
+
+/* functions in the realmode part */
+extern int enable_a20(void);
+extern void initregs(struct biosregs *regs);
+extern void intcall(uint8_t int_no, const struct biosregs *ireg, struct biosregs *oreg);
+extern void boot_puts(char*);
+extern void __attribute__((noreturn)) die(void);
+extern void __attribute__((noreturn)) protected_mode_jump(void);
+
+struct gdt_ptr {
+	uint16_t len;
+	uint32_t ptr;
+} __attribute__((packed));
+
+/* These functions are used to reference data in other segments. */
+
+static inline uint16_t ds(void)
+{
+	uint16_t seg;
+	asm("movw %%ds,%0" : "=rm" (seg));
+	return seg;
+}
+
+static inline void set_fs(uint16_t seg)
+{
+	asm volatile("movw %0,%%fs" : : "rm" (seg));
+}
+
+static inline uint16_t fs(void)
+{
+	uint16_t seg;
+	asm volatile("movw %%fs,%0" : "=rm" (seg));
+	return seg;
+}
+
+static inline void set_gs(uint16_t seg)
+{
+	asm volatile("movw %0,%%gs" : : "rm" (seg));
+}
+
+static inline uint16_t gs(void)
+{
+	uint16_t seg;
+	asm volatile("movw %%gs,%0" : "=rm" (seg));
+	return seg;
+}
+
+typedef unsigned int addr_t;
+
+static inline uint8_t rdfs8(addr_t addr)
+{
+	uint8_t v;
+	asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr));
+	return v;
+}
+static inline uint16_t rdfs16(addr_t addr)
+{
+	uint16_t v;
+	asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(uint16_t *)addr));
+	return v;
+}
+static inline uint32_t rdfs32(addr_t addr)
+{
+	uint32_t v;
+	asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
+	return v;
+}
+
+static inline void wrfs8(uint8_t v, addr_t addr)
+{
+	asm volatile("movb %1,%%fs:%0" : "+m" (*(uint8_t *)addr) : "qi" (v));
+}
+static inline void wrfs16(uint16_t v, addr_t addr)
+{
+	asm volatile("movw %1,%%fs:%0" : "+m" (*(uint16_t *)addr) : "ri" (v));
+}
+static inline void wrfs32(uint32_t v, addr_t addr)
+{
+	asm volatile("movl %1,%%fs:%0" : "+m" (*(uint32_t *)addr) : "ri" (v));
+}
+
+static inline uint8_t rdgs8(addr_t addr)
+{
+	uint8_t v;
+	asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(uint8_t *)addr));
+	return v;
+}
+static inline uint16_t rdgs16(addr_t addr)
+{
+	uint16_t v;
+	asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(uint16_t *)addr));
+	return v;
+}
+static inline uint32_t rdgs32(addr_t addr)
+{
+	uint32_t v;
+	asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
+	return v;
+}
+
+static inline void wrgs8(uint8_t v, addr_t addr)
+{
+	asm volatile("movb %1,%%gs:%0" : "+m" (*(uint8_t *)addr) : "qi" (v));
+}
+static inline void wrgs16(uint16_t v, addr_t addr)
+{
+	asm volatile("movw %1,%%gs:%0" : "+m" (*(uint16_t *)addr) : "ri" (v));
+}
+static inline void wrgs32(uint32_t v, addr_t addr)
+{
+	asm volatile("movl %1,%%gs:%0" : "+m" (*(uint32_t *)addr) : "ri" (v));
+}
+
+/** use the built in memset function for the real mode code */
+#define memset(d,c,l) __builtin_memset(d,c,l)
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* BOOT_BOOT_H */
Index: barebox-2009.12.0/arch/x86/boot/boot_hdisk.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/boot_hdisk.S
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Loading the barebox image from a disk drive in LBA mode
+ */
+
+/**
+ * @fn void real_start(void)
+ * @brief A very simple and small loader to fetch all required sectors
+ * from the boot media.
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+	.file "boot_hdisk.S"
+	.code16
+
+	/*
+	 * These symbols are generated by the linker, because they need a
+	 * special layout. This layout is needed to be able to setup this
+	 * bootloader by patching the binary when it gets stored into the
+	 * master boot record.
+	 */
+	.extern indirect_sector_lba
+	.extern boot_stack
+	.extern start_pre_uboot
+	.extern boot_disk
+	.section .boot_code, "ax"
+
+	.globl real_start
+	.type real_start, @function
+
+real_start:
+
+	xorw %ax, %ax	/* set up %ds and %ss as offset from 0 */
+	movw %ax, %ds
+	movw %ax, %ss
+
+	/* set up the REAL stack */
+	movw $boot_stack, %sp
+
+	sti		/* we're safe again */
+
+	/* save drive reference first thing! */
+	movb %dl, boot_disk
+	pushw %dx
+
+	movw $notification_string, %si
+	call output_message
+
+	/*
+	 * This boot code only supports LBA. We fail here, if the BIOS
+	 * does not support LBA for the harddisk
+	 */
+
+	/* check if LBA is supported */
+	movb $0x41, %ah
+	movw $0x55aa, %bx
+	int $0x13
+
+	/*
+	 *  %dl may have been clobbered by INT 13, AH=41H.
+	 *  This happens, for example, with AST BIOS 1.04.
+	 */
+	popw %dx
+	pushw %dx
+
+	/* stop if no LBA support */
+	jc no_lba
+	cmpw $0xaa55, %bx
+	jne no_lba
+	andw $1, %cx
+	jz no_lba
+
+lba_mode:
+	/*
+	 * Load the indirect sector. Its content is ready for use,
+	 * provided by the installer
+	 */
+	movw $indirect_sector_lba, %si
+	movb $0x42, %ah
+	int $0x13
+	jc no_lba	/* error? Then die */
+
+	/*
+	 * Now loop through all valid entries in the indirect sector
+	 */
+	movw $indirect_area, %si
+
+load_loop:
+	/*
+	 * Stop if this "Disk Address Packet Structure" is invalid
+	 * We call it invalid, if the size member is zero. If it is invalid
+	 * we are optimistic and calling the loaded image
+	 */
+	movw (%si), %ax
+	cmpw $0x0000, %ax
+	je start_main
+
+	/*
+	 * Load this entry
+	 */
+	movb $0x42, %ah
+	int $0x13
+	jc no_lba
+
+	addw (%si), %si	/* next entry */
+	cmpw $indirect_area + 512, %si
+	jne load_loop
+	/*
+	 * fall through to start u-boot.
+	 */
+start_main:
+	movw $jmp_string, %si
+	call output_message
+	jmp start_pre_uboot
+/*
+ * die if there is no LBA support
+ */
+no_lba:	movw $chs_string, %si
+	call output_message
+	hlt
+
+/*
+ * message: write the string pointed to by %si
+ *
+ *   WARNING: trashes %si, %ax, and %bx
+ */
+
+/*
+ * Use BIOS "int 10H Function 0Eh" to write character in teletype mode
+ *	%ah = 0xe	%al = character
+ *	%bh = page	%bl = foreground color (graphics modes)
+ */
+
+1:
+	movw	$0x0001, %bx
+	movb	$0xe, %ah
+	int	$0x10		/* display this char */
+
+output_message:
+	lodsb
+	cmpb	$0, %al
+	jne	1b	/* if not end of string, next char */
+	ret
+
+/* ---------------------------------------------------------------------- */
+
+	.section .boot_data
+
+notification_string:	.asciz "UBOOT2 "
+chs_string:	.asciz "CHS "
+jmp_string:	.asciz "JMP "
+
+#endif
Index: barebox-2009.12.0/arch/x86/boot/boot_main.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/boot_main.S
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * This code was inspired by the GRUB2 project.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Common boot sector main routine to be entered by the BIOS
+ */
+/**
+ * @fn void _start(void)
+ *
+ * @brief Fix segment:offset settings of some buggy BIOSs
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+	.file "boot_main.S"
+	.code16
+
+	.extern real_start
+
+	.section .boot_start, "ax"
+	.type _start, @function
+
+	/*
+	 * The BIOS loads this code to address 0x00007c00.
+	 * The code should be called with CS:IP 0:0x7c00 (hopefully).
+	 */
+	.globl _start
+_start:
+	cli		/* we're not safe here! */
+	/*
+	 * It seems there are implementations in the wild which call this
+	 * code with CS:IP 0x07C0:0000 instead. We fix it immediately.
+	 */
+	ljmp $0, $real_start
+
+	.size _start, .-_start
+
+#endif
Index: barebox-2009.12.0/arch/x86/boot/main_entry.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/main_entry.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Start of the 32 bit flat mode
+ */
+
+#include <string.h>
+
+/* These symbols are generated by the linker */
+extern char __bss_start;
+extern char __bss_end;
+
+extern void start_barebox(void);
+
+/**
+ * Called plainly from assembler that switches from real to flat mode
+ *
+ * @note The C environment isn't initialized yet
+ */
+void uboot_entry(void)
+{
+	/* clear the BSS first */
+	memset(&__bss_start, 0x00, &__bss_end - &__bss_start);
+	start_barebox();
+}
Index: barebox-2009.12.0/arch/x86/boot/pmjump.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/pmjump.S
@@ -0,0 +1,89 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief The actual transition into protected mode
+ *
+ * Note: This function is running in flat and real mode. Due to some
+ * other restrictions it must running from an address space below 0x10000
+ */
+
+/**
+ * @fn void protected_mode_jump(void)
+ * @brief Switches the first time from real mode to flat mode
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+#include <asm/modes.h>
+#include "boot.h"
+
+	.file "pmjump.S"
+	.code16
+	.section .boot.text.protected_mode_jump, "ax"
+
+	.globl	protected_mode_jump
+	.type	protected_mode_jump, @function
+
+protected_mode_jump:
+	jmp 1f			/* Short jump to serialize on 386/486 */
+1:
+
+	movw $__BOOT_DS, %cx
+	movw $__BOOT_TSS, %di
+
+	movl %cr0, %edx
+	orb $X86_CR0_PE, %dl	/* enable protected mode */
+	movl %edx, %cr0
+
+	/* Transition to 32-bit flat mode */
+	data32  ljmp $__BOOT_CS, $in_pm32
+
+/* ------------------------------------------------------------------------ */
+
+	.section ".text.in_pm32","ax"
+	.code32
+
+	.extern uboot_entry
+	.extern __bss_end
+
+	.type	in_pm32, @function
+in_pm32:
+	# Set up data segments for flat 32-bit mode
+	movl %ecx, %ds
+	movl %ecx, %es
+	movl %ecx, %fs
+	movl %ecx, %gs
+	movl %ecx, %ss
+/*
+ * Our flat mode code uses its own stack area behind the bss. With this we
+ * are still able to return to real mode temporarely
+ */
+	movl $__bss_end + 32768, %esp
+
+	# Set up TR to make Intel VT happy
+	ltr %di
+
+	# Clear registers to allow for future extensions to the
+	# 32-bit boot protocol
+	xorl %ecx, %ecx
+	xorl %edx, %edx
+	xorl %ebx, %ebx
+	xorl %ebp, %ebp
+	xorl %edi, %edi
+
+	# Set up LDTR to make Intel VT happy
+	lldt %cx
+
+	jmp uboot_entry
+
+	.size protected_mode_jump, .-protected_mode_jump
+
+#endif
Index: barebox-2009.12.0/arch/x86/boot/prepare_uboot.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/prepare_uboot.c
@@ -0,0 +1,86 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * Prepare the machine for transition to protected mode.
+ */
+#include <asm/segment.h>
+#include <asm/modes.h>
+#include <asm/io.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+/*
+ * While we are in flat mode, we can't handle interrupts. But we can't
+ * switch them off for ever in the PIC, because we need them again while
+ * entering real mode code again and again....
+ */
+static void __bootcode realmode_switch_hook(void)
+{
+	asm volatile("cli");
+	outb(0x80, 0x70); /* Disable NMI */
+	io_delay();
+}
+
+/*
+ * Reset IGNNE# if asserted in the FPU.
+ */
+static void __bootcode reset_coprocessor(void)
+{
+	outb(0, 0xf0);
+	io_delay();
+	outb(0, 0xf1);
+	io_delay();
+}
+
+/**
+ * Setup and register the global descriptor table (GDT)
+ *
+ * @note This is for the first time only
+ */
+static void __bootcode setup_gdt(void)
+{
+	/* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
+	   of the gdt_ptr contents.  Thus, make it static so it will
+	   stay in memory, at least long enough that we switch to the
+	   proper kernel GDT. */
+	static struct gdt_ptr __bootdata gdt_ptr;
+
+	gdt_ptr.len = gdt_size - 1;
+	gdt_ptr.ptr = (uint32_t)&gdt + (ds() << 4);
+
+	asm volatile("lgdtl %0" : : "m" (gdt_ptr));
+}
+
+static char a20_message[] __bootdata = "A20 gate not responding, unable to boot...\n";
+
+/*
+ * Actual invocation sequence
+ */
+void __bootcode start_pre_uboot(void)
+{
+	/* Hook before leaving real mode, also disables interrupts */
+	realmode_switch_hook();
+
+	/* Enable the A20 gate */
+	if (enable_a20()) {
+		boot_puts(a20_message);
+		die();
+	}
+
+	/* Reset coprocessor (IGNNE#) */
+	reset_coprocessor();
+
+	setup_gdt();
+	/* Actual transition to protected mode... */
+	protected_mode_jump();
+}
Index: barebox-2009.12.0/arch/x86/boot/regs.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/regs.c
@@ -0,0 +1,34 @@
+/* -----------------------------------------------------------------------
+ *
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2 or (at your
+ *   option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Simple helper function for initializing a register set.
+ *
+ * Note that this sets EFLAGS_CF in the input register set; this
+ * makes it easier to catch functions which do nothing but don't
+ * explicitly set CF.
+ */
+
+#include <asm/segment.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+void __bootcode initregs(struct biosregs *reg)
+{
+	memset(reg, 0, sizeof *reg);
+	reg->eflags |= X86_EFLAGS_CF;
+	reg->ds = ds();
+	reg->es = ds();
+	reg->fs = fs();
+	reg->gs = gs();
+}
Index: barebox-2009.12.0/arch/x86/boot/tty.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/boot/tty.c
@@ -0,0 +1,45 @@
+/* -*- linux-c -*- ------------------------------------------------------- *
+ *
+ *   Copyright (C) 1991, 1992 Linus Torvalds
+ *   Copyright 2007 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation; author H. Peter Anvin
+ *
+ *   This file is part of the Linux kernel, and is made available under
+ *   the terms of the GNU General Public License version 2.
+ *
+ * ----------------------------------------------------------------------- */
+
+/**
+ * @file
+ * @brief Very simple screen I/O for the initialization stage
+ *
+ * @todo Probably should add very simple serial I/O?
+ * @attention This is real mode code!
+ */
+
+#include <asm/segment.h>
+#include "boot.h"
+
+/* be aware of: */
+THIS_IS_REALMODE_CODE
+
+static void __bootcode putchar(int ch)
+{
+	struct biosregs ireg;
+
+	if (ch == '\n')
+		putchar('\r');	/* \n -> \r\n */
+
+	initregs(&ireg);
+	ireg.bx = 0x0007;
+	ireg.cx = 0x0001;
+	ireg.ah = 0x0e;
+	ireg.al = ch;
+	intcall(0x10, &ireg, NULL);
+}
+
+void __bootcode boot_puts(char *str)
+{
+	while (*str)
+		putchar(*str++);
+}

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 08/14] Add a generic PC platform
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (6 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 07/14] Add functions to be able to boot with BIOSs help Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 09/14] Bring in the time reference for the x86 platforms Juergen Beisert
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_generic_platform.diff --]
[-- Type: text/plain, Size: 12320 bytes --]

This code adds a generic x86 platform, enabling barebox to act as a
bootloader like 'GRUB'. Very minimalistic, yet. Supports only a serial console
and is tested with QEMU only.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 Documentation/boards.dox           |    2 
 arch/x86/configs/generic_defconfig |  186 +++++++++++++++++++++++++++++++++++++
 board/x86_generic/Makefile         |    1 
 board/x86_generic/config.h         |   21 ++++
 board/x86_generic/env/bin/boot     |   37 +++++++
 board/x86_generic/env/bin/init     |   15 ++
 board/x86_generic/env/config       |   31 ++++++
 board/x86_generic/generic_pc.c     |  140 +++++++++++++++++++++++++++
 8 files changed, 432 insertions(+), 1 deletion(-)

Index: barebox-2009.12.0/board/x86_generic/Makefile
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/Makefile
@@ -0,0 +1 @@
+obj-y += generic_pc.o
Index: barebox-2009.12.0/board/x86_generic/generic_pc.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/generic_pc.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Generic PC support to let barebox acting as a boot loader
+ */
+
+#include <common.h>
+#include <types.h>
+#include <driver.h>
+#include <init.h>
+#include <asm/syslib.h>
+#include <ns16550.h>
+
+static struct memory_platform_data ram_pdata = {
+	.name		= "ram0",
+	.flags		= DEVFS_RDWR,
+};
+
+static struct device_d sdram_dev = {
+	.name		= "mem",
+	.size		= 16 * 1024 * 1024,
+	.map_base	= 0,
+	.platform_data	= &ram_pdata,
+};
+
+static struct device_d bios_disk_dev = {
+	.name		= "biosdrive",
+	.size		= 1,
+};
+
+/*
+ * These datas are from the MBR, created by the linker and filled by the
+ * setup tool while installing barebox on the disk drive
+ */
+extern uint64_t pers_env_storage;
+extern uint16_t pers_env_size;
+extern uint8_t pers_env_drive;
+
+/**
+ * Persistant environment "not used" marker.
+ * Note: Must be in accordance to the value the tool "setup_mbr" writes.
+ */
+#define PATCH_AREA_PERS_SIZE_UNUSED 0x000
+
+static int devices_init(void)
+{
+	int rc;
+
+	sdram_dev.size = bios_get_memsize();	/* extended memory only */
+	sdram_dev.size <<= 10;
+
+	register_device(&sdram_dev);
+	register_device(&bios_disk_dev);
+
+	if (pers_env_size != PATCH_AREA_PERS_SIZE_UNUSED) {
+		rc = devfs_add_partition("disk0",	/* FIXME */
+				pers_env_storage * 512,
+				(unsigned)pers_env_size * 512,
+				DEVFS_PARTITION_FIXED, "env0");
+		printf("Partition: %d\n", rc);
+	} else
+		printf("No persistant storage defined\n");
+
+        return 0;
+}
+device_initcall(devices_init);
+
+#ifdef CONFIG_DRIVER_SERIAL_NS16550
+
+static struct NS16550_plat serial_plat = {
+       .clock = 1843200,
+       .f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR,
+       .reg_read = x86_uart_read,
+       .reg_write = x86_uart_write,
+};
+
+/* we are expecting always one serial interface */
+static struct device_d generic_pc_serial_device = {
+       .name = "serial_ns16550",
+       .map_base = 0x3f8,
+       .size = 8,
+       .platform_data = (void *)&serial_plat,
+};
+
+static int pc_console_init(void)
+{
+       /* Register the serial port */
+       return register_device(&generic_pc_serial_device);
+}
+console_initcall(pc_console_init);
+
+#endif
+
+/** @page generic_pc Generic PC based bootloader
+
+This platform acts as a generic PC based bootloader. It depends on at least
+one boot media that is connected locally (no network boot) and can be
+handled by the regular BIOS (any kind of hard disks for example).
+
+The created @a barebox image can be used to boot a standard x86 bzImage
+Linux kernel.
+
+Refer section @ref x86_bootloader_preparations how to do so.
+
+How to get the binary image:
+
+Using the default configuration:
+
+@code
+make ARCH=x86 generic_defconfig
+@endcode
+
+Build the binary image:
+
+@code
+make ARCH=x86 CROSS_COMPILE=x86compiler
+@endcode
+
+@note replace the 'x86compiler' with your x86 (cross) compiler.
+
+*/
Index: barebox-2009.12.0/board/x86_generic/env/config
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/env/config
@@ -0,0 +1,31 @@
+#
+# basic config
+#
+# boot source: 'disk' or 'net'
+kernel=disk
+root=disk
+
+# data for the NFS case
+nfsroot="/path/to/nfs_root"
+
+# data for the disk case
+kernel_device=/dev/biosdisk0.1
+rootpart_disk=/dev/sda1
+rootpart_fs=ext2
+
+baudrate=115200
+serial=ttyS0
+
+# use UART for console
+bootargs="console=$serial,$baudrate"
+
+autoboot_timeout=3
+
+# use 'dhcp' to do dhcp in uboot and in kernel
+#  ip=dhcp
+# or set your networking parameters here
+#  eth0.ipaddr=192.168.3.11
+#  eth0.netmask=255.255.255.0
+#  eth0.gateway=a.b.c.d
+#  eth0.serverip=192.168.3.10
+#  eth0.ethaddr=aa.bb.cc.dd.ee.ff
Index: barebox-2009.12.0/board/x86_generic/config.h
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/config.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/* nothing special yet */
Index: barebox-2009.12.0/board/x86_generic/env/bin/init
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/env/bin/init
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+PATH=/env/bin
+export PATH
+
+. /env/config
+
+echo
+echo -n "Hit any key to stop autoboot: "
+timeout -a $autoboot_timeout
+if [ $? != 0 ]; then
+        exit
+fi
+
+boot
Index: barebox-2009.12.0/arch/x86/configs/generic_defconfig
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/configs/generic_defconfig
@@ -0,0 +1,186 @@
+#
+# Automatically generated make config: don't edit
+# barebox version: 2009.12.0-x86-trunk
+#
+CONFIG_ARCH_TEXT_BASE=0x00007c00
+CONFIG_BOARDINFO="Generic x86 bootloader"
+# CONFIG_BOARD_LINKER_SCRIPT is not set
+CONFIG_GENERIC_LINKER_SCRIPT=y
+CONFIG_X86=y
+CONFIG_MACH_X86_GENERIC=y
+CONFIG_X86_BIOS_BRINGUP=y
+# CONFIG_X86_NATIVE_BRINGUP is not set
+
+#
+# BIOS boot source              
+#
+CONFIG_X86_HDBOOT=y
+
+#
+# Board specific settings       
+#
+CONFIG_GREGORIAN_CALENDER=y
+CONFIG_HAS_KALLSYMS=y
+CONFIG_HAS_MODULES=y
+CONFIG_CMD_MEMORY=y
+CONFIG_ENV_HANDLING=y
+
+#
+# General Settings              
+#
+CONFIG_LOCALVERSION_AUTO=y
+
+#
+# memory layout                 
+#
+CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
+CONFIG_TEXT_BASE=0x00007c00
+CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
+CONFIG_MEMORY_LAYOUT_DEFAULT=y
+# CONFIG_MEMORY_LAYOUT_FIXED is not set
+CONFIG_STACK_SIZE=0x7000
+CONFIG_MALLOC_SIZE=0x400000
+CONFIG_BROKEN=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_MODULES is not set
+# CONFIG_KALLSYMS is not set
+CONFIG_PROMPT="uboot:"
+CONFIG_BAUDRATE=115200
+CONFIG_LONGHELP=y
+CONFIG_CBSIZE=1024
+CONFIG_MAXARGS=16
+CONFIG_SHELL_HUSH=y
+# CONFIG_SHELL_SIMPLE is not set
+CONFIG_GLOB=y
+CONFIG_PROMPT_HUSH_PS2="> "
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_DYNAMIC_CRC_TABLE=y
+CONFIG_ERRNO_MESSAGES=y
+CONFIG_TIMESTAMP=y
+CONFIG_CONSOLE_FULL=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+# CONFIG_OF_FLAT_TREE is not set
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="board/x86_generic/env"
+
+#
+# Debugging                     
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_FLASH_NOISE is not set
+# CONFIG_ENABLE_PARTITION_NOISE is not set
+# CONFIG_ENABLE_DEVICE_NOISE is not set
+
+#
+# Commands                      
+#
+
+#
+# scripting                     
+#
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+# CONFIG_CMD_TRUE is not set
+# CONFIG_CMD_FALSE is not set
+
+#
+# file commands                 
+#
+CONFIG_CMD_LS=y
+CONFIG_CMD_RM=y
+CONFIG_CMD_CAT=y
+CONFIG_CMD_MKDIR=y
+CONFIG_CMD_RMDIR=y
+CONFIG_CMD_CP=y
+CONFIG_CMD_PWD=y
+CONFIG_CMD_CD=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UMOUNT=y
+
+#
+# console                       
+#
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO=y
+
+#
+# memory                        
+#
+# CONFIG_CMD_LOADB is not set
+# CONFIG_CMD_LOADY is not set
+# CONFIG_CMD_LOADS is not set
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_CRC is not set
+# CONFIG_CMD_MTEST is not set
+
+#
+# flash                         
+#
+# CONFIG_CMD_FLASH is not set
+
+#
+# booting                       
+#
+# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_LINUX16=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+# CONFIG_CMD_PARTITION is not set
+CONFIG_CMD_TEST=y
+CONFIG_CMD_VERSION=y
+CONFIG_CMD_HELP=y
+CONFIG_CMD_DEVINFO=y
+# CONFIG_NET is not set
+
+#
+# Drivers                       
+#
+
+#
+# serial drivers                
+#
+CONFIG_DRIVER_SERIAL_NS16550=y
+
+#
+# SPI drivers                   
+#
+# CONFIG_SPI is not set
+# CONFIG_I2C is not set
+
+#
+# flash drivers                 
+#
+# CONFIG_DRIVER_CFI is not set
+# CONFIG_DRIVER_CFI_OLD is not set
+# CONFIG_NAND is not set
+CONFIG_ATA=y
+
+#
+# drive types
+#
+CONFIG_ATA_DISK=y
+
+#
+# interface types
+#
+CONFIG_ATA_BIOS=y
+# CONFIG_USB is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_VIDEO is not set
+
+#
+# Filesystem support            
+#
+# CONFIG_FS_CRAMFS is not set
+CONFIG_FS_RAMFS=y
+CONFIG_FS_DEVFS=y
+CONFIG_CRC32=y
+# CONFIG_GENERIC_FIND_NEXT_BIT is not set
Index: barebox-2009.12.0/board/x86_generic/env/bin/boot
===================================================================
--- /dev/null
+++ barebox-2009.12.0/board/x86_generic/env/bin/boot
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+. /env/config
+
+if [ x$1 = xdisk ]; then
+	root=disk
+	kernel=disk
+fi
+
+if [ x$1 = xnet ]; then
+	root=net
+	kernel=net
+fi
+
+if [ x$ip = xdhcp ]; then
+	bootargs="$bootargs ip=dhcp"
+else
+	bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask:::"
+fi
+
+if [ x$root = xdisk ]; then
+	bootargs="$bootargs root=$rootpart_disk rootfstype=$rootpart_fs rw"
+else
+	bootargs="$bootargs root=/dev/nfs nfsroot=$eth0.serverip:$nfsroot,v3,tcp rw"
+fi
+
+if [ $kernel = net ]; then
+	if [ x$ip = xdhcp ]; then
+		dhcp
+	fi
+	tftp $uimage uImage || exit 1
+	bootm uImage
+else
+	bootargs="BOOT_IMAGE=$kernel_device auto $bootargs"
+	linux16 $kernel_device
+fi
+
Index: barebox-2009.12.0/Documentation/boards.dox
===================================================================
--- barebox-2009.12.0.orig/Documentation/boards.dox
+++ barebox-2009.12.0/Documentation/boards.dox
@@ -27,7 +27,7 @@ Blackfin type:
 
 x86 type:
 
-@li nothing yet
+@li @subpage generic_pc
 
 coldfire/m68k type:
 

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 09/14] Bring in the time reference for the x86 platforms
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (7 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 08/14] Add a generic PC platform Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 10/14] Start to add ATA support to barebox Juergen Beisert
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_timer.diff --]
[-- Type: text/plain, Size: 2961 bytes --]

This code uses the always (hopefully) existing PIT device to get the time
reference for barebox.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/mach-i386/Makefile    |    3 +
 arch/x86/mach-i386/pit_timer.c |   71 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 74 insertions(+)

Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/pit_timer.c
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/pit_timer.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Clocksource based on the 'Programmable Interval Timer' PIT (8253)
+ *
+ * This timer should be available on almost all PCs. It also should be run
+ * at a fixed frequency (1193181.8181 Hz) and not modified to use another
+ * reload value than 0xFFFF. So, it always counts from 0xffff down to 0.
+ *
+ * @note: We can't reprogram the PIT, it will be still used by the BIOS. This
+ * clocksource driver does not touch any PIT settings.
+ */
+
+#include <init.h>
+#include <clock.h>
+#include <asm/io.h>
+
+/** base address of the PIT in a standard PC */
+#define PIT 0x40
+
+static uint64_t pit_clocksource_read(void)
+{
+	uint16_t val1, val2;
+
+	outb(0x00, PIT + 3);	/* latch counter 0 */
+	outb(0x00, 0x80);
+
+	val1 = inb(PIT);
+	outb(0x00, 0x80);
+
+	val2 = inb(PIT);
+	val2 <<= 8;
+
+	/* note: its a down counter */
+	return 0xFFFFU - (val1 | val2);
+}
+
+static struct clocksource cs = {
+	.read	= pit_clocksource_read,
+	.mask	= 0x0000ffff,
+	.shift	= 10,
+};
+
+static int clocksource_init (void)
+{
+	cs.mult = clocksource_hz2mult(1193182, cs.shift);
+	init_clock(&cs);
+
+	return 0;
+}
+
+core_initcall(clocksource_init);
Index: u-boot-2.0.0-rc10/arch/x86/mach-i386/Makefile
===================================================================
--- u-boot-2.0.0-rc10.orig/arch/x86/mach-i386/Makefile
+++ u-boot-2.0.0-rc10/arch/x86/mach-i386/Makefile
@@ -1,2 +1,5 @@
 obj-y += generic.o
 obj-y += reset.o
+
+# reference clocksource
+obj-y += pit_timer.o

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 10/14] Start to add ATA support to barebox
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (8 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 09/14] Bring in the time reference for the x86 platforms Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 11/14] Add the main disk driver Juergen Beisert
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: ata_devices.diff --]
[-- Type: text/plain, Size: 3445 bytes --]

Add the basic files, declarations and folders to bring in ATA support.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 drivers/Kconfig      |    1 +
 drivers/Makefile     |    1 +
 drivers/ata/Kconfig  |   12 ++++++++++++
 drivers/ata/Makefile |    3 +++
 include/ata.h        |   39 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 56 insertions(+)

Index: u-boot-2.0.0-rc10/drivers/ata/Kconfig
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/drivers/ata/Kconfig
@@ -0,0 +1,12 @@
+menuconfig ATA
+	bool "ATA                           "
+	help
+	  Add support for ATA types of drives like harddisks and CDROMs.
+
+if ATA
+
+comment "drive types"
+
+comment "interface types"
+
+endif
Index: u-boot-2.0.0-rc10/drivers/ata/Makefile
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/drivers/ata/Makefile
@@ -0,0 +1,3 @@
+# drive types
+
+# interface types
Index: u-boot-2.0.0-rc10/include/ata.h
===================================================================
--- /dev/null
+++ u-boot-2.0.0-rc10/include/ata.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Declarations to communicate with ATA types of drives
+ */
+
+#include <types.h>
+#include <driver.h>
+
+/**
+ * Access functions from drives through the specified interface
+ */
+struct ata_interface {
+	/** write a count of sectors from a buffer to the drive */
+	int (*write)(struct device_d*, uint64_t, unsigned, const void*);
+	/** read a count of sectors from the drive into the buffer */
+	int (*read)(struct device_d*, uint64_t, unsigned, void*);
+	/** private interface data */
+	void *priv;
+};
Index: u-boot-2.0.0-rc10/drivers/Kconfig
===================================================================
--- u-boot-2.0.0-rc10.orig/drivers/Kconfig
+++ u-boot-2.0.0-rc10/drivers/Kconfig
@@ -6,6 +6,7 @@ source "drivers/spi/Kconfig"
 source "drivers/i2c/Kconfig"
 source "drivers/nor/Kconfig"
 source "drivers/nand/Kconfig"
+source "drivers/ata/Kconfig"
 source "drivers/usb/Kconfig"
 source "drivers/video/Kconfig"
 
Index: u-boot-2.0.0-rc10/drivers/Makefile
===================================================================
--- u-boot-2.0.0-rc10.orig/drivers/Makefile
+++ u-boot-2.0.0-rc10/drivers/Makefile
@@ -3,6 +3,7 @@ obj-y	+= serial/
 obj-y	+= nand/
 obj-y	+= nor/
 obj-y	+= usb/
+obj-$(CONFIG_ATA) += ata/
 obj-$(CONFIG_SPI) += spi/
 obj-$(CONFIG_I2C) += i2c/
 obj-$(CONFIG_VIDEO) += video/

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 11/14] Add the main disk driver
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (9 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 10/14] Start to add ATA support to barebox Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 12/14] Add a low level disk drive access driver Juergen Beisert
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_ata_disk.diff --]
[-- Type: text/plain, Size: 10667 bytes --]

This is the generic disk driver. It does not know how to access the drives.
Other low level drivers are required for this.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 drivers/ata/Kconfig      |    5 
 drivers/ata/Makefile     |    2 
 drivers/ata/disk_drive.c |  346 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 353 insertions(+)

Index: barebox-2009.12.0/drivers/ata/Kconfig
===================================================================
--- barebox-2009.12.0.orig/drivers/ata/Kconfig
+++ barebox-2009.12.0/drivers/ata/Kconfig
@@ -7,6 +7,11 @@ if ATA
 
 comment "drive types"
 
+config ATA_DISK
+	bool "disk drives"
+	help
+	  Add support for regular disk drives
+
 comment "interface types"
 
 endif
Index: barebox-2009.12.0/drivers/ata/Makefile
===================================================================
--- barebox-2009.12.0.orig/drivers/ata/Makefile
+++ barebox-2009.12.0/drivers/ata/Makefile
@@ -1,3 +1,5 @@
 # drive types
 
+obj-$(CONFIG_ATA_DISK) += disk_drive.o
+
 # interface types
Index: barebox-2009.12.0/drivers/ata/disk_drive.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/drivers/ata/disk_drive.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Generic disk drive support
+ *
+ * @todo Support for disks larger than 4 GiB
+ */
+
+#include <stdio.h>
+#include <init.h>
+#include <driver.h>
+#include <types.h>
+#include <ata.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <string.h>
+#include <linux/kernel.h>
+
+/**
+ * Description of one partition table entry (D*S type)
+ */
+struct partition_entry {
+	uint8_t boot_indicator;
+	uint8_t chs_begin[3];
+	uint8_t type;
+	uint8_t chs_end[3];
+	uint32_t partition_start;
+	uint32_t partition_size;
+} __attribute__ ((packed));
+
+/** one for all */
+#define SECTOR_SIZE 512
+
+/**
+ * Guess the size of the disk, based on the partition table entries
+ * @param dev device to create partitions for
+ * @param table partition table
+ * @return size in sectors
+ */
+static unsigned long disk_guess_size(struct device_d *dev, struct partition_entry *table)
+{
+	int part_order[4] = {0, 1, 2, 3};
+	unsigned long size = 0;
+	int i;
+
+	/* TODO order the partitions */
+
+	for (i = 0; i < 4; i++) {
+		if (table[part_order[i]].partition_start != 0) {
+			size += table[part_order[i]].partition_start - size; /* the gap */
+			size += table[part_order[i]].partition_size;
+		}
+	}
+#if 1
+/* limit disk sizes we can't handle due to 32 bit limits */
+	if (size > 0x7fffff) {
+		dev_warn(dev, "Warning: Size limited due to 32 bit contraints\n");
+		size = 0x7fffff;
+	}
+#endif
+	return size;
+}
+
+/**
+ * Register partitions found on the drive
+ * @param dev device to create partitions for
+ * @param table partition table
+ * @return 0 on success
+ */
+static int disk_register_partitions(struct device_d *dev, struct partition_entry *table)
+{
+	int part_order[4] = {0, 1, 2, 3};
+	int i, rc;
+	char drive_name[16], partition_name[19];
+
+	/* TODO order the partitions */
+
+	for (i = 0; i < 4; i++) {
+		sprintf(drive_name, "%s%d", dev->name, dev->id);
+		sprintf(partition_name, "%s%d.%d", dev->name, dev->id, i);
+		if (table[part_order[i]].partition_start != 0) {
+#if 1
+/* ignore partitions we can't handle due to 32 bit limits */
+			if (table[part_order[i]].partition_start > 0x7fffff)
+				continue;
+			if (table[part_order[i]].partition_size > 0x7fffff)
+				continue;
+#endif
+			dev_info(dev, "Registering partition %s to drive %s\n", partition_name, drive_name);
+			rc = devfs_add_partition(drive_name,
+				table[part_order[i]].partition_start * SECTOR_SIZE,
+				table[part_order[i]].partition_size * SECTOR_SIZE,
+				DEVFS_PARTITION_FIXED, partition_name);
+			if (rc != 0)
+				dev_err(dev, "Failed to register partition %s (%d)\n", partition_name, rc);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * Write some data to a disk
+ * @param cdev the device to write to
+ * @param _buf source of data
+ * @param count byte count to write
+ * @param offset where to write to disk
+ * @param flags Ignored
+ * @return Written bytes or negative value in case of failure
+ */
+static ssize_t disk_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
+{
+	struct device_d *dev = cdev->dev;
+	struct ata_interface *intf = dev->platform_data;
+	int rc;
+	unsigned sep_count = offset & (SECTOR_SIZE - 1);
+	ssize_t written = 0;
+
+	/* starting at no sector boundary? */
+	if (sep_count != 0) {
+		uint8_t tmp_buf[SECTOR_SIZE];
+		unsigned to_write = min(SECTOR_SIZE - sep_count, count);
+
+		rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot read data\n");
+			return -1;
+		}
+		memcpy(&tmp_buf[sep_count], _buf, to_write);
+		rc = intf->write(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot write data\n");
+			return -1;
+		}
+
+		_buf += to_write;
+		offset += to_write;
+		count -= to_write;
+		written += to_write;
+	}
+
+	/* full sector part */
+	sep_count = count / SECTOR_SIZE;
+	if (sep_count) {
+		rc = intf->write(dev, offset / SECTOR_SIZE, sep_count, _buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot write data\n");
+			return -1;
+		}
+		_buf += sep_count * SECTOR_SIZE;
+		offset += sep_count * SECTOR_SIZE;
+		count -= sep_count * SECTOR_SIZE;
+		written += sep_count * SECTOR_SIZE;
+	}
+
+	/* ending at no sector boundary? */
+	if (count) {
+		uint8_t tmp_buf[SECTOR_SIZE];
+
+		rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot read data\n");
+			return -1;
+		}
+		memcpy(tmp_buf, _buf, count);
+		rc = intf->write(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot write data\n");
+			return -1;
+		}
+		written += count;
+	}
+
+	return written;
+}
+
+/**
+ * Read some data from a disk
+ * @param cdev the device to read from
+ * @param _buf destination of the data
+ * @param count byte count to read
+ * @param offset where to read from
+ * @param flags Ignored
+ * @return Read bytes or negative value in case of failure
+ */
+static ssize_t disk_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
+{
+	struct device_d *dev = cdev->dev;
+	struct ata_interface *intf = dev->platform_data;
+	int rc;
+	unsigned sep_count = offset & (SECTOR_SIZE - 1);
+	ssize_t read = 0;
+
+	/* starting at no sector boundary? */
+	if (sep_count != 0) {
+		uint8_t tmp_buf[SECTOR_SIZE];
+		unsigned to_read = min(SECTOR_SIZE - sep_count, count);
+
+		rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot read data\n");
+			return -1;
+		}
+		memcpy(_buf, &tmp_buf[sep_count], to_read);
+		_buf += to_read;
+		offset += to_read;
+		count -= to_read;
+		read += to_read;
+	}
+
+	/* full sector part */
+	sep_count = count / SECTOR_SIZE;
+	if (sep_count) {
+		rc = intf->read(dev, offset / SECTOR_SIZE, sep_count, _buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot read data\n");
+			return -1;
+		}
+		_buf += sep_count * SECTOR_SIZE;
+		offset += sep_count * SECTOR_SIZE;
+		count -= sep_count * SECTOR_SIZE;
+		read += sep_count * SECTOR_SIZE;
+	}
+
+	/* ending at no sector boundary? */
+	if (count) {
+		uint8_t tmp_buf[SECTOR_SIZE];
+
+		rc = intf->read(dev, offset / SECTOR_SIZE, 1, tmp_buf);
+		if (rc != 0) {
+			dev_err(dev, "Cannot read data\n");
+			return -1;
+		}
+		memcpy(_buf, tmp_buf, count);
+		read += count;
+	}
+
+	return read;
+}
+
+static struct file_operations disk_ops = {
+	.read  = disk_read,
+	.write = disk_write,
+	.lseek = dev_lseek_default,
+};
+
+/**
+ * Probe the connected disk drive
+ */
+static int disk_probe(struct device_d *dev)
+{
+	uint8_t sector[512];
+	int rc;
+	struct ata_interface *intf = dev->platform_data;
+	struct cdev *disk_cdev;
+
+	rc = intf->read(dev, 0, 1, sector);
+	if (rc != 0) {
+		dev_err(dev, "Cannot read MBR of this device\n");
+		return -1;
+	}
+
+	/* It seems a valuable disk. Register it */
+	disk_cdev = xzalloc(sizeof(struct cdev));
+	if (disk_cdev == NULL) {
+		dev_err(dev, "Out of memory\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * BIOS based disks needs special handling. Not the driver can
+	 * enumerate the hardware, the BIOS did it already. To show the user
+	 * the drive ordering must not correspond to the Linux drive order,
+	 * use the 'biosdisk' name instead.
+	 */
+#ifdef CONFIG_ATA_BIOS
+	if (strcmp(dev->driver->name, "biosdisk") == 0)
+		disk_cdev->name = asprintf("biosdisk%d", dev->id);
+	else
+#endif
+		disk_cdev->name = asprintf("disk%d", dev->id);
+	/**
+	 * @todo we need the size of the drive, else its nearly impossible
+	 * to do anything with it (at least with the generic routines)
+	 */
+	disk_cdev->size = 32;	/* FIXME */
+	disk_cdev->ops = &disk_ops;
+	disk_cdev->dev = dev;
+	devfs_create(disk_cdev);
+
+	if ((sector[510] != 0x55) || (sector[511] != 0xAA)) {
+		dev_info(dev, "No partition table found\n");
+		return 0;
+	}
+
+	/* guess the size of this drive */
+	dev->size = disk_guess_size(dev, (struct partition_entry*)&sector[446]) * SECTOR_SIZE;
+	dev_info(dev, "Drive size guessed to %u kiB\n", dev->size / 1024);
+	disk_cdev->size = dev->size;
+
+	disk_register_partitions(dev, (struct partition_entry*)&sector[446]);
+
+	return 0;
+}
+
+#ifdef CONFIG_ATA_BIOS
+static struct driver_d biosdisk_driver = {
+        .name   = "biosdisk",
+        .probe  = disk_probe,
+};
+#endif
+
+static struct driver_d disk_driver = {
+        .name   = "disk",
+        .probe  = disk_probe,
+};
+
+static int disk_init(void)
+{
+#ifdef CONFIG_ATA_BIOS
+	register_driver(&biosdisk_driver);
+#endif
+	register_driver(&disk_driver);
+	return 0;
+}
+
+device_initcall(disk_init);

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 12/14] Add a low level disk drive access driver
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (10 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 11/14] Add the main disk driver Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 13/14] Add a special command to load and start a bzImage on x86 Juergen Beisert
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_bios_disk-driver.diff --]
[-- Type: text/plain, Size: 13993 bytes --]

This is a low level disk drive communication driver. It uses the real mode
BIOS found on most x86 platforms, to read and write sectors. Used by the
generic disk driver.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/lib/Makefile    |    1 
 arch/x86/lib/bios_disk.S |   77 ++++++++++++
 drivers/ata/Kconfig      |    9 +
 drivers/ata/Makefile     |    2 
 drivers/ata/bios.c       |  291 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 380 insertions(+)

Index: barebox-2009.12.0/drivers/ata/Kconfig
===================================================================
--- barebox-2009.12.0.orig/drivers/ata/Kconfig
+++ barebox-2009.12.0/drivers/ata/Kconfig
@@ -14,4 +14,13 @@ config ATA_DISK
 
 comment "interface types"
 
+config ATA_BIOS
+	bool "BIOS based"
+	depends on X86_BIOS_BRINGUP
+	help
+	  Gain disk drive access via int13 calls to the standard PC-BIOS.
+	  The advantage of this driver is, it still uses user's defined boot
+	  media to work on. Disadvantage is: Due to its 16 bit nature it is
+	  slow.
+
 endif
Index: barebox-2009.12.0/drivers/ata/Makefile
===================================================================
--- barebox-2009.12.0.orig/drivers/ata/Makefile
+++ barebox-2009.12.0/drivers/ata/Makefile
@@ -3,3 +3,5 @@
 obj-$(CONFIG_ATA_DISK) += disk_drive.o
 
 # interface types
+
+obj-$(CONFIG_ATA_BIOS) += bios.o
Index: barebox-2009.12.0/drivers/ata/bios.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/drivers/ata/bios.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Media communication layer through the standard 16 bit PC-BIOS
+ *
+ * This communication driver does all accesses to the boot medium via 16 bit
+ * real mode calls into the standard BIOS. Due to this method, its possible
+ * to use all the medias to boot from that are supported by the BIOS. This
+ * also includes emulated only medias.
+ *
+ * To be able to call the real mode BIOS, this driver must switch back to
+ * real mode for each access. This will slow down the access a little bit, but
+ * we are a boot loader here, not an operating system...
+ *
+ * Note: We need scratch memory for the BIOS communication, because the BIOS
+ * can only handle memory below 0xA0000. So we must copy all data between
+ * the flat mode buffers and realmode buffers.
+ *
+ * Note: This driver makes no sense on other architectures than x86.
+ *
+ * Note: This driver does only support LBA addressing. Currently no CHS!
+ */
+
+#include <stdio.h>
+#include <linux/types.h>
+#include <init.h>
+#include <driver.h>
+#include <string.h>
+#include <xfuncs.h>
+#include <asm/syslib.h>
+#include <ata.h>
+#include <errno.h>
+
+/**
+ * Sector count handled in one count
+ *
+ * @todo 127 are always possible, some BIOS manufacturer supports up to 255.
+ * Is it's worth to detect Phoenic's restriction?
+ */
+#define SECTORS_AT_ONCE 64
+
+/** Size of one sector in bytes */
+#define SECTOR_SIZE 512
+
+/** Command to read sectors from media */
+#define BIOS_READ_CMD 0
+
+/** Command to write sectors to media */
+#define BIOS_WRT_CMD 1
+
+/**
+ * "Disk Address Packet Structure" to be used when calling
+ * BIOS's int13, function 0x42/0x43
+ */
+struct DAPS
+{
+	uint8_t size;		/**< always '16' */
+	uint8_t res1;		/**< always '0' */
+	int8_t count;		/**< number of sectors 0...127 */
+	uint8_t res2;		/**< always '0' */
+	uint16_t offset;	/**< buffer address: offset */
+	uint16_t segment;	/**< buffer address: segment */
+	uint64_t lba;		/**< LBA of the start sector */
+} __attribute__ ((packed));
+
+/**
+ * Collection of data we need to know about the connected drive
+ */
+struct media_access {
+	int drive_no;	/**< drive number used by the BIOS */
+	int is_cdrom;	/**< drive is a CDROM e.g. no write support */
+};
+
+/**
+ * Scratch memory for BIOS communication to handle data in chunks of 32 kiB
+ *
+ * Note: This variable is located in the .bss segment, assuming it is located
+ * below 0xA0000. If not, the BIOS is not able to read or store any data
+ * from/to it. The variable must also aligned to a 16 byte boundary to easify
+ * linear to segment:offset address conversion.
+ */
+static uint8_t scratch_buffer[SECTORS_AT_ONCE * SECTOR_SIZE] __attribute__((aligned(16)));
+
+/**
+ * Communication buffer for the 16 bit int13 BIOS call
+ *
+ * Note: This variable is located in the .bss segment, assuming it is located
+ * below 0xA0000. If not, the BIOS is not able to read or store any data
+ * from/to it. The variable must also aligned to a 16 byte boundary to easify
+ * linear to segment:offset conversion.
+ */
+static struct DAPS bios_daps __attribute__((aligned(16)));
+
+/**
+ * @param media our data we need to do the access
+ * @param cmd Command to forward to the BIOS
+ * @param sector_start LBA of the start sector
+ * @param sector_count Sector count
+ * @param buffer Buffer to read from or write to (in the low memory area)
+ * @return 0 on success, anything else on failure
+ */
+static int biosdisk_bios_call(struct media_access *media, int cmd, uint64_t sector_start, unsigned sector_count, void *buffer)
+{
+	int rc;
+
+	/* prepare the DAPS for the int13 call */
+	bios_daps.size = sizeof(struct DAPS);
+	bios_daps.res1 = 0;
+	bios_daps.count = sector_count;	/* always less than 128! */
+	bios_daps.res2 = 0;
+	bios_daps.segment = (unsigned long)buffer >> 4;
+	bios_daps.offset = (unsigned long)buffer - (unsigned long)(bios_daps.segment << 4);
+	bios_daps.lba = sector_start;
+
+	if (cmd == BIOS_READ_CMD)
+		rc = bios_disk_rw_int13_extensions(0x42, media->drive_no, &bios_daps);
+	else if (cmd == BIOS_WRT_CMD)
+		rc = bios_disk_rw_int13_extensions(0x43, media->drive_no, &bios_daps);
+	else
+		return -1;
+
+	return rc;
+}
+
+/**
+ * Read a chunk of sectors from media
+ * @param dev our data we need to do the access
+ * @param sector_start Sector's LBA number to start read from
+ * @param sector_count Sectors to read
+ * @param buffer Buffer to read into
+ * @return 0 on success, anything else on failure
+ *
+ * This routine expects the buffer has the correct size to store all data!
+ */
+static int biosdisk_read(struct device_d *dev, uint64_t sector_start, unsigned sector_count, void *buffer)
+{
+	int rc;
+	struct ata_interface *intf = dev->platform_data;
+	struct media_access *media = intf->priv;
+
+	while (sector_count >= SECTORS_AT_ONCE) {
+		rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer);
+		if (rc != 0)
+			return rc;
+		__builtin_memcpy(buffer, scratch_buffer, sizeof(scratch_buffer));
+		buffer += sizeof(scratch_buffer);
+		sector_start += SECTORS_AT_ONCE;
+		sector_count -= SECTORS_AT_ONCE;
+	};
+
+	/* Are sectors still remaining? */
+	if (sector_count) {
+		rc = biosdisk_bios_call(media, BIOS_READ_CMD, sector_start, sector_count, scratch_buffer);
+		__builtin_memcpy(buffer, scratch_buffer, sector_count * SECTOR_SIZE);
+	} else
+		rc = 0;
+
+	return rc;
+}
+
+/**
+ * Write a chunk of sectors to media
+ * @param dev our data we need to do the access
+ * @param sector_start Sector's LBA number to start write to
+ * @param sector_count Sectors to write
+ * @param buffer Buffer to write from
+ * @return 0 on success, anything else on failure
+ *
+ * This routine expects the buffer has the correct size to read all data!
+ */
+static int biosdisk_write(struct device_d *dev, uint64_t sector_start, unsigned sector_count, const void *buffer)
+{
+	int rc;
+	struct ata_interface *intf = dev->platform_data;
+	struct media_access *media = intf->priv;
+
+	while (sector_count >= SECTORS_AT_ONCE) {
+		__builtin_memcpy(scratch_buffer, buffer, sizeof(scratch_buffer));
+		rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, SECTORS_AT_ONCE, scratch_buffer);
+		if (rc != 0)
+			return rc;
+		buffer += sizeof(scratch_buffer);
+		sector_start += SECTORS_AT_ONCE;
+		sector_count -= SECTORS_AT_ONCE;
+	};
+
+	/* Are sectors still remaining? */
+	if (sector_count) {
+		__builtin_memcpy(scratch_buffer, buffer, sector_count * SECTOR_SIZE);
+		rc = biosdisk_bios_call(media, BIOS_WRT_CMD, sector_start, sector_count, scratch_buffer);
+	} else
+		rc = 0;
+
+	return rc;
+}
+
+/**
+ * Probe for connected drives and register them
+ *
+ * Detecting if a drive is present is done by simply reading its MBR.
+ *
+ * FIXME: Relation between BIOS disk numbering scheme and our representation
+ * here in barebox (and later on in the linux kernel)
+ */
+static int biosdisk_probe(struct device_d *dev)
+{
+	int drive, rc;
+	struct media_access media, *m;
+	struct device_d *drive_dev;
+	struct ata_interface *p;
+
+	for (drive = 0x80; drive < 0x90; drive++) {
+		media.drive_no = drive;
+		media.is_cdrom = 0;	/* don't know yet */
+		rc = biosdisk_bios_call(&media, BIOS_READ_CMD, 0, 1, scratch_buffer);
+		if (rc != 0)
+			continue;
+
+		printf("BIOSdrive %d seems valid. Registering...\n", media.drive_no);
+
+		drive_dev = xzalloc(sizeof(struct device_d) + sizeof(struct media_access) + sizeof(struct ata_interface));
+		if (drive_dev == NULL) {
+			dev_err(dev, "Out of memory\n");
+			return -1;
+		}
+		m = (struct media_access*)&drive_dev[1];
+		p = (struct ata_interface*)&m[1];
+
+		m->drive_no = drive;
+		m->is_cdrom = 0;
+
+		p->write = biosdisk_write;
+		p->read = biosdisk_read;
+		p->priv = m;
+
+		strcpy(drive_dev->name, "biosdisk");
+		drive_dev->id = drive - 0x80;
+		drive_dev->size = 1;
+		drive_dev->map_base = 0;
+		drive_dev->platform_data = p;
+
+		register_device(drive_dev);
+	}
+
+	return 0;
+}
+
+static struct driver_d biosdisk_driver = {
+        .name   = "biosdrive",
+        .probe  = biosdisk_probe,
+};
+
+static int biosdisk_init(void)
+{
+	/* sanity */
+	if (scratch_buffer > (uint8_t*)0x9FFFF) {
+		printf("BIOS driver: Scratch memory not in real mode area. Cannot continue!\n");
+		return -EIO;
+	}
+	if (&bios_daps > (struct DAPS*)0x9FFFF) {
+		printf("BIOS driver: DAPS memory not in real mode area. Cannot continue!\n");
+		return -EIO;
+	}
+
+	register_driver(&biosdisk_driver);
+	return 0;
+}
+
+device_initcall(biosdisk_init);
Index: barebox-2009.12.0/arch/x86/lib/Makefile
===================================================================
--- barebox-2009.12.0.orig/arch/x86/lib/Makefile
+++ barebox-2009.12.0/arch/x86/lib/Makefile
@@ -5,3 +5,4 @@ obj-y += gdt.o
 # needed, when running via a 16 bit BIOS
 obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o
 obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o
+obj-$(CONFIG_X86_BIOS_BRINGUP) += bios_disk.o
Index: barebox-2009.12.0/arch/x86/lib/bios_disk.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/bios_disk.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Do BIOS calls to load or save data from disks
+ *
+ * @note These functions are running in flat and real mode. Due to some
+ * other restrictions these routines must running from an address
+ * space below 0x10000
+ */
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+/*
+ *   int bios_disk_rw_int13_extensions (int ah, int drive, void *dap)
+ *
+ *   Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
+ *   is passed for disk address packet. If an error occurs, return
+ *   non-zero, otherwise zero.
+ */
+	.section .boot.text.bios_disk_rw_int13_extensions, "ax"
+	.code32
+	.globl bios_disk_rw_int13_extensions
+	.type bios_disk_rw_int13_extensions, @function
+
+	.extern prot_to_real
+	.extern real_to_prot
+
+bios_disk_rw_int13_extensions:
+	pushl %ebp
+	pushl %esi
+
+	/* compute the address of disk_address_packet */
+	movw %cx, %si
+	xorw %cx, %cx
+	shrl $4, %ecx	/* save the segment to cx */
+
+	movb %al, %dh
+	call prot_to_real	/* enter real mode right now */
+
+	.code16
+	movb %dh, %ah
+	movw %cx, %ds
+	int $0x13		/* do the operation */
+	movb %ah, %dl		/* save return value */
+	/* back to protected mode */
+	DATA32 call real_to_prot
+
+	.code32
+	movb %dl, %al	/* return value in %eax */
+
+	popl %esi
+	popl %ebp
+
+	ret
+
+#endif

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 13/14] Add a special command to load and start a bzImage on x86
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (11 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 12/14] Add a low level disk drive access driver Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-12 10:15 ` [PATCHv2 14/14] Add the whole x86 architecture to the build system Juergen Beisert
  2010-01-14  9:29 ` [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Sascha Hauer
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_linux16_command.diff --]
[-- Type: text/plain, Size: 17361 bytes --]

Other architectures are supporting the uImage format used by barebox's 'bootm'
command. x86 does'nt. So, we need a special command to be able to boot the
x86 specific bzImage format.

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 Documentation/commands.dox    |    2 
 arch/x86/include/asm/syslib.h |    4 
 arch/x86/lib/Makefile         |    1 
 arch/x86/lib/linux_start.S    |   75 ++++++++
 commands/Kconfig              |    8 
 commands/Makefile             |    1 
 commands/linux16.c            |  363 ++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 453 insertions(+), 1 deletion(-)

Index: barebox-2009.12.0/commands/Kconfig
===================================================================
--- barebox-2009.12.0.orig/commands/Kconfig
+++ barebox-2009.12.0/commands/Kconfig
@@ -219,6 +219,14 @@ config CMD_BOOTU
 	   compile in the 'bootu' command to start raw (uncompressed)
 	   Linux images
 
+config CMD_LINUX16
+	tristate
+	default y if X86
+	prompt "linux16"
+	help
+	  Compile the linux16 command to be able to boot bzImages
+	  via real mode.
+
 config CMD_RESET
 	tristate
 	prompt "reset"
Index: barebox-2009.12.0/commands/Makefile
===================================================================
--- barebox-2009.12.0.orig/commands/Makefile
+++ barebox-2009.12.0/commands/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_CMD_BOOTM)		+= bootm.o
+obj-$(CONFIG_CMD_LINUX16)	+= linux16.o
 obj-$(CONFIG_CMD_LOADB)		+= loadb.o xyzModem.o
 obj-$(CONFIG_CMD_LOADY)		+= loadb.o xyzModem.o
 obj-$(CONFIG_CMD_LOADS)		+= loads.o
Index: barebox-2009.12.0/commands/linux16.c
===================================================================
--- /dev/null
+++ barebox-2009.12.0/commands/linux16.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * In parts from the GRUB2 project:
+ *
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008  Free Software Foundation, Inc.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <fs.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/syslib.h>
+
+/** FIXME */
+#define LINUX_MAGIC_SIGNATURE       0x53726448      /* "HdrS" */
+
+/** FIXME */
+#define LINUX_FLAG_BIG_KERNEL       0x1
+
+/** FIXME */
+#define LINUX_BOOT_LOADER_TYPE      0x72
+
+/** FIXME */
+#define LINUX_DEFAULT_SETUP_SECTS	4
+
+/** FIXME */
+#define LINUX_MAX_SETUP_SECTS		64
+
+/** FIXME */
+#define LINUX_OLD_REAL_MODE_SEGMT	0x9000
+
+/** FIXME */
+#define LINUX_OLD_REAL_MODE_ADDR	(LINUX_OLD_REAL_MODE_SEGMT << 4)
+
+/** FIXME */
+#define LINUX_HEAP_END_OFFSET		(LINUX_OLD_REAL_MODE_SEGMT - 0x200)
+
+/** FIXME */
+#define LINUX_FLAG_CAN_USE_HEAP		0x80
+
+/** Define kernel command lines's start offset in the setup segment */
+#define LINUX_CL_OFFSET			0x9000
+
+/** Define kernel command lines's end offset */
+#define LINUX_CL_END_OFFSET		0x90FF
+
+/** FIXME */
+#define LINUX_CL_MAGIC			0xA33F
+
+/** FIXME */
+#define LINUX_SETUP_MOVE_SIZE		0x9100
+
+/** Sector size */
+#define DISK_SECTOR_BITS		9
+#define DISK_SECTOR_SIZE		0x200
+
+/** Where to load a bzImage */
+#define LINUX_BZIMAGE_ADDR		0x100000
+
+struct linux_kernel_header {
+	/* first sector of the image */
+	uint8_t code1[0x0020];
+	uint16_t cl_magic;		/**< Magic number 0xA33F */
+	uint16_t cl_offset;		/**< The offset of command line */
+	uint8_t code2[0x01F1 - 0x0020 - 2 - 2];
+	uint8_t setup_sects;		/**< The size of the setup in sectors */
+	uint16_t root_flags;		/**< If the root is mounted readonly */
+	uint16_t syssize;		/**< obsolete */
+	uint16_t swap_dev;		/**< obsolete */
+	uint16_t ram_size;		/**< obsolete */
+	uint16_t vid_mode;		/**< Video mode control */
+	uint16_t root_dev;		/**< Default root device number */
+	uint16_t boot_flag;		/**< 0xAA55 magic number */
+
+	/* second sector of the image */
+	uint16_t jump;			/**< Jump instruction (this is code!) */
+	uint32_t header;		/**< Magic signature "HdrS" */
+	uint16_t version;		/**< Boot protocol version supported */
+	uint32_t realmode_swtch;	/**< Boot loader hook */
+	uint16_t start_sys;		/**< The load-low segment (obsolete) */
+	uint16_t kernel_version;	/**< Points to kernel version string */
+	uint8_t type_of_loader;		/**< Boot loader identifier */
+#define LINUX_LOADER_ID_LILO		0x0
+#define LINUX_LOADER_ID_LOADLIN		0x1
+#define LINUX_LOADER_ID_BOOTSECT	0x2
+#define LINUX_LOADER_ID_SYSLINUX	0x3
+#define LINUX_LOADER_ID_ETHERBOOT	0x4
+#define LINUX_LOADER_ID_ELILO		0x5
+#define LINUX_LOADER_ID_GRUB		0x7
+#define LINUX_LOADER_ID_UBOOT		0x8
+#define LINUX_LOADER_ID_XEN		0x9
+#define LINUX_LOADER_ID_GUJIN		0xa
+#define LINUX_LOADER_ID_QEMU		0xb
+	uint8_t loadflags;		/**< Boot protocol option flags */
+	uint16_t setup_move_size;	/**< Move to high memory size */
+	uint32_t code32_start;		/**< Boot loader hook */
+	uint32_t ramdisk_image;		/**< initrd load address */
+	uint32_t ramdisk_size;		/**< initrd size */
+	uint32_t bootsect_kludge;	/**< obsolete */
+	uint16_t heap_end_ptr;		/**< Free memory after setup end */
+	uint8_t ext_loader_ver;		/**< boot loader's extension of the version number */
+	uint8_t ext_loader_type;	/**< boot loader's extension of its type */
+	char *cmd_line_ptr;		/**< Points to the kernel command line */
+	uint32_t initrd_addr_max;	/**< Highest address for initrd */
+#if 0
+	/* for the records only. These members are defined in
+	 * more recent Linux kernels
+	 */
+	uint32_t kernel_alignment;	/**< Alignment unit required by the kernel */
+	uint8_t relocatable_kernel;	/** */
+	uint8_t min_alignment;		/** */
+	uint32_t cmdline_size;		/** */
+	uint32_t hardware_subarch;	/** */
+	uint64_t hardware_subarch_data;	/** */
+	uint32_t payload_offset;	/** */
+	uint32_t payload_length;	/** */
+	uint64_t setup_data;		/** */
+	uint64_t pref_address;		/** */
+	uint32_t init_size;		/** */
+#endif
+} __attribute__ ((packed));
+
+/**
+ * Load an x86 Linux kernel bzImage and start it
+ * @param cmdtp FIXME
+ * @param argc parameter count
+ * @param argv list of parameter
+ *
+ * Loads an x86 bzImage, checks for its integrity, stores the two parts
+ * (setup = 'real mode code' and kernel = 'protected mode code') to their
+ * default locations, switches back to real mode and runs the setup code.
+ */
+static int do_linux16(cmd_tbl_t *cmdtp, int argc, char *argv[])
+{
+	struct linux_kernel_header *lh = NULL;
+	int rc;
+	unsigned setup_sects;
+	unsigned real_mode_size;
+	size_t image_size;
+	const char *cmdline = getenv("bootargs");
+
+	if (argc < 2) {
+		perror("linux16");
+		return 1;
+	}
+
+	lh = read_file(argv[1], &image_size);
+	if (lh == NULL) {
+		printf("Cannot read file '%s'\n", argv[1]);
+		return 1;
+	}
+
+	if (lh->boot_flag != 0xaa55) {
+		printf("File '%s' has invalid magic number\n", argv[1]);
+		rc = 1;
+		goto on_error;
+	}
+
+	if (lh->setup_sects > LINUX_MAX_SETUP_SECTS) {
+		printf("File '%s' contains too many setup sectors\n", argv[1]);
+		rc = 1;
+		goto on_error;
+	}
+
+	setup_sects = lh->setup_sects;
+
+	printf("Found a %d.%d image header\n", lh->version >> 8, lh->version & 0xFF);
+
+	if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200) {
+		/* kernel is recent enough */
+		;
+		if (!(lh->loadflags & LINUX_FLAG_BIG_KERNEL)) {
+			printf("Cannot load a classic zImage. Use a bzImage instead\n");
+			goto on_error;
+		}
+		lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;	/* TODO */
+
+		if (lh->version >= 0x0201) {
+			lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
+			lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
+		}
+
+		if (lh->version >= 0x0202)
+			lh->cmd_line_ptr = (void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET);	/* FIXME */
+		else {
+			lh->cl_magic = LINUX_CL_MAGIC;
+			lh->cl_offset = LINUX_CL_OFFSET;
+			lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
+		}
+	} else {
+		printf("Kernel too old to handle\n");
+		rc = 1;
+		goto on_error;
+	}
+
+	if (strlen(cmdline) >= (LINUX_CL_END_OFFSET -  LINUX_CL_OFFSET)) {
+		printf("Kernel command line exceeds the available space\n");
+		rc = 1;
+		goto on_error;
+	}
+
+	/* If SETUP_SECTS is not set, set it to the default.  */
+	if (setup_sects == 0) {
+		printf("Fixing setup sector count\n");
+		setup_sects = LINUX_DEFAULT_SETUP_SECTS;
+	}
+
+	if (setup_sects >= 15) {
+		void *src = lh;
+		if (lh->kernel_version != 0)
+			printf("Kernel version: '%s'\n", src + lh->kernel_version + DISK_SECTOR_SIZE);
+	}
+
+	/*
+	 * Size of the real mode part to handle in a separate way
+	 */
+	real_mode_size = (setup_sects << DISK_SECTOR_BITS) + DISK_SECTOR_SIZE;
+
+	/*
+	 *                real mode space                     hole            extended memory
+	 * |---------------------------------------------->|----------->|------------------------------>
+	 * 0                                            0xa0000     0x100000
+	 *  <-1-|----------2-----------><-3-   |
+	 *    0x7e00                        0x90000
+	 *                                <-4--|-5-->                   |---------6------------->
+	 *
+	 * 1) real mode stack
+	 * 2) barebox code
+	 * 3) flat mode stack
+	 * 4) realmode stack when starting a Linux kernel
+	 * 5) Kernel's real mode setup code
+	 * 6) compressed kernel image
+	 */
+	/*
+	 * Parts of the image we know:
+	 * - real mode part
+	 * - kernel payload
+	 */
+	/*
+	 * NOTE: This part is dangerous, as it copies some image content to
+	 * various locations in the main memory. This could overwrite important
+	 * data of the running barebox (hopefully not)
+	 */
+	/* copy the real mode part of the image to the 9th segment */
+	memcpy((void*)LINUX_OLD_REAL_MODE_ADDR, lh, LINUX_SETUP_MOVE_SIZE);
+
+	/* TODO add 'BOOT_IMAGE=<file>' and 'auto' if no user intervention was done (in front of all other params) */
+	/* copy also the command line into this area */
+	memcpy((void*)(LINUX_OLD_REAL_MODE_ADDR + LINUX_CL_OFFSET), cmdline, strlen(cmdline) + 1);
+	printf("Using kernel command line: '%s'\n", cmdline);
+
+	/* copy the compressed image part to its final address the setup code expects it
+	 * Note: The protected mode part starts at offset (setup_sects + 1) * 512
+	 */
+	memcpy((void*)LINUX_BZIMAGE_ADDR, ((void*)lh) + real_mode_size, image_size - real_mode_size);
+
+	/*
+	 * switch back to real mode now and start the real mode part of the
+	 * image at address "(LINUX_OLD_REAL_MODE_ADDR >> 4) + 0x20:0x0000"
+	 * which means "0x9020:0x000" -> 0x90200
+	 */
+	bios_start_linux(LINUX_OLD_REAL_MODE_SEGMT);	/* does not return */
+
+on_error:
+	if (lh != NULL)
+		free(lh);
+
+	return rc;
+}
+
+static const __maybe_unused char cmd_linux16_help[] =
+"Usage: linux16 <file>\n"
+"Boot a linux kernel via real mode code\n";
+
+
+BAREBOX_CMD_START(linux16)
+	.cmd		= do_linux16,
+	.usage		= "boot linux kernel",
+	BAREBOX_CMD_HELP(cmd_linux16_help)
+BAREBOX_CMD_END
+
+/**
+ * @file
+ * @brief Boot support for Linux on x86
+ */
+
+/**
+ * @page linux16_command linux16: Boot a bzImage kernel on x86
+ *
+ * Usage is: linux16 \<file\>
+ *
+ * Boot a linux kernel via real mode code. Only kernel images in the
+ * @p bzImage format are supported.
+ */
+
+/**
+ * @page x86_boot_preparation Linux Preparation on x86
+ *
+ * Due to some real mode constraints, starting Linux is somehow tricky.
+ * Currently only @p bzImages are supported, because @p zImages would
+ * interfere with the @a barebox runtime.
+ * Also older load header versions than 2.00 aren't supported.
+ *
+ * The memory layout immediately before starting the Linux kernel:
+ *
+@verbatim
+                  real mode space                     hole            extended memory
+   |---------------------------------------------->|----------->|------------------------------>
+   0  0x7e00                        0x90000     0xa0000     0x100000
+    <-1-|----------2-----------><-3-   |
+                                  <-4--|-5-->                   |---------6------------->
+@endverbatim
+ *
+ * @li 1 = @a barebox's real mode stack
+ * @li 2 = @a barebox's code
+ * @li 3 = @a barebox's flat mode stack
+ * @li 4 = real mode stack, when starting the Linux kernel
+ * @li 5 = Kernel's real mode setup code
+ * @li 6 = compressed kernel image
+ *
+ * A more detailed memory layout for kernel's real mode setup code
+ *
+@verbatim
+
+   0x90000                                    0x97fff   0x99000              0x990ff
+   ---|------------------------------------------|----------------|--------------------|
+      |<-------- max setup code size ----------->|<--heap/stack-->|<-- command line -->|
+
+@endverbatim
+ *
+ * The regular entry point into the setup code is 0x90200 (2nd sector)
+ *
+ * To start the kernel, it's own setup code will be called. To do so, it
+ * must be called in real mode. So, @a barebox switches back to real mode
+ * a last time and does a jump to the setup code entry point. Now its up to
+ * the setup code to deflate the kernel, switching to its own protected mode
+ * setup and starting the kernel itself.
+ *
+ * @note This scenario only works, if a BIOS is still present. In this case
+ * there is no need for @a barebox to forward any system related information
+ * to the kernel. Everything is detected by kernel's setup code.
+ *
+ */
Index: barebox-2009.12.0/arch/x86/include/asm/syslib.h
===================================================================
--- barebox-2009.12.0.orig/arch/x86/include/asm/syslib.h
+++ barebox-2009.12.0/arch/x86/include/asm/syslib.h
@@ -27,3 +27,7 @@ extern int bios_disk_rw_int13_extensions
 extern uint16_t bios_get_memsize(void);
 
 #endif
+
+#ifdef CONFIG_CMD_LINUX16
+extern void bios_start_linux(unsigned) __attribute__((regparm(1)));
+#endif
Index: barebox-2009.12.0/arch/x86/lib/Makefile
===================================================================
--- barebox-2009.12.0.orig/arch/x86/lib/Makefile
+++ barebox-2009.12.0/arch/x86/lib/Makefile
@@ -6,3 +6,4 @@ obj-y += gdt.o
 obj-$(CONFIG_X86_BIOS_BRINGUP) += memory16.o
 obj-$(CONFIG_X86_BIOS_BRINGUP) += traveler.o
 obj-$(CONFIG_X86_BIOS_BRINGUP) += bios_disk.o
+obj-$(CONFIG_CMD_LINUX16) += linux_start.o
Index: barebox-2009.12.0/arch/x86/lib/linux_start.S
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/lib/linux_start.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * Mostly stolen from the GRUB2 project
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008  Free Software Foundation, Inc.
+ *
+ * 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 the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+/**
+ * @file
+ * @brief Start the Linux real mode setup code
+ *
+ * Note: These functions are running in flat and real mode. Due to some
+ * other restrictions these routines must running from an address
+ * space below 0x10000
+ */
+
+/*
+ *   void bios_start_linux(unsigned segment)
+ *
+ */
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+	.section .boot.text.bios_start_linux, "ax"
+	.code32
+	.globl bios_start_linux
+	.type bios_start_linux, @function
+
+	.extern prot_to_real
+
+bios_start_linux:
+	/* 'prot_to_real' eats our eax content */
+	movl %eax, %ebx
+	addl $0x20, %eax
+	movw %ax, setup_seg
+
+	call prot_to_real
+
+	.code16
+
+	cli
+	/* all segment registers are using the same segment */
+	movw %bx, %ss
+	movw %bx, %ds
+	movw %bx, %es
+	movw %bx, %fs
+	movw %bx, %gs
+
+	/* stack for the setup code (end of heap) */
+	movw $0x9000, %sp
+
+	/* do an 'ljmp' and never return */
+	.byte	0xea
+	.word	0
+setup_seg:
+	.word	0
+
+	.code32
+
+#endif
Index: barebox-2009.12.0/Documentation/commands.dox
===================================================================
--- barebox-2009.12.0.orig/Documentation/commands.dox
+++ barebox-2009.12.0/Documentation/commands.dox
@@ -20,5 +20,5 @@
 @li @subpage setenv_command
 @li @subpage sh_command
 @li @subpage unprotect_command
-
+@li @subpage linux16_command
 */

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCHv2 14/14] Add the whole x86 architecture to the build system
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (12 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 13/14] Add a special command to load and start a bzImage on x86 Juergen Beisert
@ 2010-01-12 10:15 ` Juergen Beisert
  2010-01-14  9:29 ` [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Sascha Hauer
  14 siblings, 0 replies; 16+ messages in thread
From: Juergen Beisert @ 2010-01-12 10:15 UTC (permalink / raw)
  To: barebox

[-- Attachment #1: add_x86_architecture.diff --]
[-- Type: text/plain, Size: 3019 bytes --]

Signed-off-by: Juergen Beisert <jbe@pengutronix.de>

---
 arch/x86/Kconfig  |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/Makefile |   50 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+)

Index: barebox-2009.12.0/arch/x86/Kconfig
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/Kconfig
@@ -0,0 +1,67 @@
+#
+#
+#
+config ARCH_TEXT_BASE
+	hex
+	default 0x00007c00 if MACH_X86_GENERIC
+
+config BOARDINFO
+	default "Generic x86 bootloader" if MACH_X86_GENERIC
+
+config BOARD_LINKER_SCRIPT
+	bool
+	default n
+
+config GENERIC_LINKER_SCRIPT
+	bool
+	default y
+	depends on !BOARD_LINKER_SCRIPT
+
+config X86
+	bool
+	select HAS_KALLSYMS
+	select HAS_MODULES
+	select HAVE_CONFIGURABLE_MEMORY_LAYOUT
+	select HAVE_CONFIGURABLE_TEXT_BASE
+	default y
+
+choice
+	prompt "Select your board"
+
+config MACH_X86_GENERIC
+	bool "Generic x86"
+	select X86_BOOTLOADER
+	help
+	  Say Y here if you want barebox to be your BIOS based bootloader
+
+endchoice
+
+choice
+	prompt "Bring up type"
+
+	config X86_BIOS_BRINGUP
+		prompt "16 bit BIOS"
+		bool
+		help
+		   Barebox will act as a BIOS based bootloader. This includes
+		   some 16 bit real mode code and some restrictions everyone knows
+		   from BIOS based systems.
+
+	config X86_NATIVE_BRINGUP
+		bool "native"
+		help
+		   Barebox will act as a native bootloader. This includes all the
+		   required initialization needed to bring up a piece of hardware.
+		   Note: Not implemented yet
+
+endchoice
+
+source arch/x86/boot/Kconfig
+source arch/x86/mach-i386/Kconfig
+
+source common/Kconfig
+source commands/Kconfig
+source net/Kconfig
+source drivers/Kconfig
+source fs/Kconfig
+source lib/Kconfig
Index: barebox-2009.12.0/arch/x86/Makefile
===================================================================
--- /dev/null
+++ barebox-2009.12.0/arch/x86/Makefile
@@ -0,0 +1,50 @@
+CPPFLAGS += -D__X86__ -fno-strict-aliasing
+
+board-y := x86_generic
+machine-y := i386
+
+TEXT_BASE = $(CONFIG_TEXT_BASE)
+
+CPPFLAGS += -march=i386 -DTEXT_BASE=$(TEXT_BASE) -P
+
+ifndef CONFIG_MODULES
+# Add cleanup flags
+CPPFLAGS += -fdata-sections -ffunction-sections
+LDFLAGS_uboot += -static --gc-sections
+endif
+
+ifeq ($(incdir-y),)
+incdir-y := $(machine-y)
+endif
+INCDIR   := arch-$(incdir-y)
+
+all: $(KBUILD_IMAGE)
+
+
+
+
+
+
+ifneq ($(board-y),)
+BOARD  := board/$(board-y)/
+else
+BOARD  :=
+endif
+
+ifneq ($(machine-y),)
+MACH  := arch/x86/mach-$(machine-y)/
+else
+MACH  :=
+endif
+
+common-y += $(BOARD) $(MACH)
+common-y += arch/x86/lib/
+common-y += arch/x86/boot/
+
+# arch/x86/cpu/
+
+lds-$(CONFIG_GENERIC_LINKER_SCRIPT)   := arch/x86/lib/barebox.lds
+lds-$(CONFIG_BOARD_LINKER_SCRIPT)     := $(BOARD)/barebox.lds
+
+CLEAN_FILES    += arch/x86/lib/barebox.lds barebox.map barebox.S
+

-- 

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCHv2 00/14] Bring in basic x86 support into 'barebox'
  2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
                   ` (13 preceding siblings ...)
  2010-01-12 10:15 ` [PATCHv2 14/14] Add the whole x86 architecture to the build system Juergen Beisert
@ 2010-01-14  9:29 ` Sascha Hauer
  14 siblings, 0 replies; 16+ messages in thread
From: Sascha Hauer @ 2010-01-14  9:29 UTC (permalink / raw)
  To: Juergen Beisert; +Cc: barebox

On Tue, Jan 12, 2010 at 11:15:34AM +0100, Juergen Beisert wrote:
> This patch series brings in some basic x86 support into the tree.
> At first this support can act as a boot loader on a BIOS based
> x86 machine like GRUB is. E.g. barebox will be stored in the MBR of
> a boot media the BIOS supports to boot from. This implementation still
> talks to the BIOS in real mode, to load or store data from/to a disk
> drive, but the barebox core itself runs in 32 bit flat mode.
> 
> Currently only a serial console is supported.
> 
> v2 of this patch series comes with some clean ups and also uses the discussed
> naming convention for BIOS based disk access. The whole series is updated to
> 'barebox' (instead of u-boot-v2). Note: Its tested only with QEMU yet. We are
> going to port it to real hardware now.
> 
> Comments are welcome.

Applied to -next.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-01-14  9:29 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-01-12 10:15 [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 01/14] Add a tool to activate barebox as a boot loader on x86 architectures Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 02/14] Consider real and protected mode in the dump file Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 03/14] Adding x86 usage documentation to the tree Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 04/14] Adding required architecture header files Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 05/14] Bring in the first x86 specific code Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 06/14] Add some generic functions to make x86 work Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 07/14] Add functions to be able to boot with BIOSs help Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 08/14] Add a generic PC platform Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 09/14] Bring in the time reference for the x86 platforms Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 10/14] Start to add ATA support to barebox Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 11/14] Add the main disk driver Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 12/14] Add a low level disk drive access driver Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 13/14] Add a special command to load and start a bzImage on x86 Juergen Beisert
2010-01-12 10:15 ` [PATCHv2 14/14] Add the whole x86 architecture to the build system Juergen Beisert
2010-01-14  9:29 ` [PATCHv2 00/14] Bring in basic x86 support into 'barebox' Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox