From 2b62b02c2c20ab9d038f19a6afd1bec0ac005fc2 Mon Sep 17 00:00:00 2001 From: florian Date: Sun, 21 Sep 2008 11:32:06 +0000 Subject: [PATCH] Remove 2.6.22 files, no target uses them anymore git-svn-id: svn://svn.openwrt.org/openwrt/trunk@12638 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- include/kernel-version.mk | 3 - .../patches-2.6.22/001-squashfs.patch | 4170 ------ .../patches-2.6.22/002-lzma_decompress.patch | 788 - .../patches-2.6.22/003-squashfs_lzma.patch | 107 - .../004-extra_optimization.patch | 12 - .../patches-2.6.22/006-gcc4_inline_fix.patch | 11 - .../patches-2.6.22/007-samsung_flash.patch | 36 - .../009-revert_intel_flash_breakage.patch | 169 - ...0-disable_old_squashfs_compatibility.patch | 19 - .../patches-2.6.22/011-mips_boot.patch | 19 - .../patches-2.6.22/012-mips_cpu_tlb.patch | 18 - .../013-mips_generic_gpio_support.patch | 32 - .../patches-2.6.22/014-x86_newsetup.patch | 11865 ---------------- .../015-x86_newsetup_fixup.patch | 19 - .../patches-2.6.22/060-block2mtd_init.patch | 112 - .../patches-2.6.22/065-rootfs_split.patch | 944 -- .../100-netfilter_layer7_2.17.patch | 2101 --- .../101-netfilter_layer7_pktmatch.patch | 109 - .../patches-2.6.22/110-ipp2p_0.8.1rc1.patch | 944 -- .../120-openswan-2.4.0.kernel-2.6-natt.patch | 166 - .../patches-2.6.22/130-netfilter_ipset.patch | 7664 ---------- .../patches-2.6.22/140-netfilter_time.patch | 239 - .../patches-2.6.22/150-netfilter_imq.patch | 869 -- .../patches-2.6.22/160-netfilter_route.patch | 948 -- .../170-netfilter_chaostables_0.8.patch | 844 -- .../patches-2.6.22/171-netfilter_tarpit.patch | 319 - .../180-netfilter_depends.patch | 20 - .../patches-2.6.22/190-netfilter_rtsp.patch | 1364 -- .../patches-2.6.22/200-sched_esfq.patch | 789 - .../201-multiple_default_gateways.patch | 336 - .../202-mips-freestanding.patch | 12 - .../patches-2.6.22/204-jffs2_eofdetect.patch | 56 - .../207-powerpc_asm_segment_h.patch | 9 - .../patches-2.6.22/208-rtl8110sb_fix.patch | 24 - .../patches-2.6.22/209-mini_fo.patch | 7779 ---------- .../210-mac80211_include_wireless_dev.patch | 806 -- .../patches-2.6.22/213-kobject_uevent.patch | 37 - .../patches-2.6.22/400-ledtrig_morse.patch | 19 - .../patches-2.6.22/410-gpio_buttons.patch | 30 - .../patches-2.6.22/510-yaffs_support.patch | 17 - .../511-yaffs_reduce_compiler_warnings.patch | 80 - .../patches-2.6.22/600-eeprom_93cx6.patch | 348 - .../601-eeprom_93cx6_fixes.patch | 31 - .../801-usb_serial_endpoint_size.patch | 25 - .../900-headers_type_and_time.patch | 46 - .../902-darwin_scripts_include.patch | 102 - .../patches-2.6.22/903-stddef_include.patch | 17 - .../patches-2.6.22/904-ls_time_locale.patch | 20 - .../patches-2.6.22/999-icplus.patch | 175 - target/linux/rb532/config-2.6.22 | 195 - 50 files changed, 44864 deletions(-) delete mode 100644 target/linux/generic-2.6/patches-2.6.22/001-squashfs.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/002-lzma_decompress.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/003-squashfs_lzma.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/004-extra_optimization.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/006-gcc4_inline_fix.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/007-samsung_flash.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/009-revert_intel_flash_breakage.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/010-disable_old_squashfs_compatibility.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/011-mips_boot.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/012-mips_cpu_tlb.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/013-mips_generic_gpio_support.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/014-x86_newsetup.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/015-x86_newsetup_fixup.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/060-block2mtd_init.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/065-rootfs_split.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/100-netfilter_layer7_2.17.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/101-netfilter_layer7_pktmatch.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/110-ipp2p_0.8.1rc1.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/120-openswan-2.4.0.kernel-2.6-natt.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/130-netfilter_ipset.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/140-netfilter_time.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/150-netfilter_imq.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/160-netfilter_route.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/170-netfilter_chaostables_0.8.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/171-netfilter_tarpit.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/180-netfilter_depends.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/190-netfilter_rtsp.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/200-sched_esfq.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/201-multiple_default_gateways.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/202-mips-freestanding.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/204-jffs2_eofdetect.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/207-powerpc_asm_segment_h.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/208-rtl8110sb_fix.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/209-mini_fo.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/210-mac80211_include_wireless_dev.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/213-kobject_uevent.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/400-ledtrig_morse.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/410-gpio_buttons.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/510-yaffs_support.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/511-yaffs_reduce_compiler_warnings.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/600-eeprom_93cx6.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/601-eeprom_93cx6_fixes.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/801-usb_serial_endpoint_size.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/900-headers_type_and_time.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/902-darwin_scripts_include.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/903-stddef_include.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/904-ls_time_locale.patch delete mode 100644 target/linux/generic-2.6/patches-2.6.22/999-icplus.patch delete mode 100644 target/linux/rb532/config-2.6.22 diff --git a/include/kernel-version.mk b/include/kernel-version.mk index e43423425..860269687 100644 --- a/include/kernel-version.mk +++ b/include/kernel-version.mk @@ -16,9 +16,6 @@ endif ifeq ($(LINUX_VERSION),2.6.21.7) LINUX_KERNEL_MD5SUM:=bc15fad1487336d5dcb0945cd039d8ed endif -ifeq ($(LINUX_VERSION),2.6.22.19) - LINUX_KERNEL_MD5SUM:=4db27facb78aeb79d06e6ae6bf0ac0b6 -endif ifeq ($(LINUX_VERSION),2.6.23.17) LINUX_KERNEL_MD5SUM:=a0300a393ac91ce9c64bf31522b45e2e endif diff --git a/target/linux/generic-2.6/patches-2.6.22/001-squashfs.patch b/target/linux/generic-2.6/patches-2.6.22/001-squashfs.patch deleted file mode 100644 index 0807d1d0c..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/001-squashfs.patch +++ /dev/null @@ -1,4170 +0,0 @@ ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -1367,6 +1367,71 @@ - - If unsure, say N. - -+config SQUASHFS -+ tristate "SquashFS 3.0 - Squashed file system support" -+ select ZLIB_INFLATE -+ help -+ Saying Y here includes support for SquashFS 3.0 (a Compressed Read-Only File -+ System). Squashfs is a highly compressed read-only filesystem for Linux. -+ It uses zlib compression to compress both files, inodes and directories. -+ Inodes in the system are very small and all blocks are packed to minimise -+ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K. -+ SquashFS 3.0 supports 64 bit filesystems and files (larger than 4GB), full -+ uid/gid information, hard links and timestamps. -+ -+ Squashfs is intended for general read-only filesystem use, for archival -+ use (i.e. in cases where a .tar.gz file may be used), and in embedded -+ systems where low overhead is needed. Further information and filesystem tools -+ are available from http://squashfs.sourceforge.net. -+ -+ If you want to compile this as a module ( = code which can be -+ inserted in and removed from the running kernel whenever you want), -+ say M here and read . The module -+ will be called squashfs. Note that the root file system (the one -+ containing the directory /) cannot be compiled as a module. -+ -+ If unsure, say N. -+ -+config SQUASHFS_EMBEDDED -+ -+ bool "Additional options for memory-constrained systems" -+ depends on SQUASHFS -+ default n -+ help -+ Saying Y here allows you to specify cache sizes and how Squashfs -+ allocates memory. This is only intended for memory constrained -+ systems. -+ -+ If unsure, say N. -+ -+config SQUASHFS_FRAGMENT_CACHE_SIZE -+ int "Number of fragments cached" if SQUASHFS_EMBEDDED -+ depends on SQUASHFS -+ default "3" -+ help -+ By default SquashFS caches the last 3 fragments read from -+ the filesystem. Increasing this amount may mean SquashFS -+ has to re-read fragments less often from disk, at the expense -+ of extra system memory. Decreasing this amount will mean -+ SquashFS uses less memory at the expense of extra reads from disk. -+ -+ Note there must be at least one cached fragment. Anything -+ much more than three will probably not make much difference. -+ -+config SQUASHFS_VMALLOC -+ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED -+ depends on SQUASHFS -+ default n -+ help -+ By default SquashFS uses kmalloc to obtain fragment cache memory. -+ Kmalloc memory is the standard kernel allocator, but it can fail -+ on memory constrained systems. Because of the way Vmalloc works, -+ Vmalloc can succeed when kmalloc fails. Specifying this option -+ will make SquashFS always use Vmalloc to allocate the -+ fragment cache memory. -+ -+ If unsure, say N. -+ - config VXFS_FS - tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)" - depends on BLOCK ---- a/fs/Makefile -+++ b/fs/Makefile -@@ -72,6 +72,7 @@ - obj-$(CONFIG_JBD2) += jbd2/ - obj-$(CONFIG_EXT2_FS) += ext2/ - obj-$(CONFIG_CRAMFS) += cramfs/ -+obj-$(CONFIG_SQUASHFS) += squashfs/ - obj-$(CONFIG_RAMFS) += ramfs/ - obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ - obj-$(CONFIG_CODA_FS) += coda/ ---- /dev/null -+++ b/fs/squashfs/inode.c -@@ -0,0 +1,2122 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * inode.c -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "squashfs.h" -+ -+static void squashfs_put_super(struct super_block *); -+static int squashfs_statfs(struct dentry *, struct kstatfs *); -+static int squashfs_symlink_readpage(struct file *file, struct page *page); -+static int squashfs_readpage(struct file *file, struct page *page); -+static int squashfs_readpage4K(struct file *file, struct page *page); -+static int squashfs_readdir(struct file *, void *, filldir_t); -+static struct inode *squashfs_alloc_inode(struct super_block *sb); -+static void squashfs_destroy_inode(struct inode *inode); -+static int init_inodecache(void); -+static void destroy_inodecache(void); -+static struct dentry *squashfs_lookup(struct inode *, struct dentry *, -+ struct nameidata *); -+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode); -+static long long read_blocklist(struct inode *inode, int index, -+ int readahead_blks, char *block_list, -+ unsigned short **block_p, unsigned int *bsize); -+static int squashfs_get_sb(struct file_system_type *, int, -+ const char *, void *, struct vfsmount *); -+ -+ -+static z_stream stream; -+ -+static struct file_system_type squashfs_fs_type = { -+ .owner = THIS_MODULE, -+ .name = "squashfs", -+ .get_sb = squashfs_get_sb, -+ .kill_sb = kill_block_super, -+ .fs_flags = FS_REQUIRES_DEV -+}; -+ -+static unsigned char squashfs_filetype_table[] = { -+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK -+}; -+ -+static struct super_operations squashfs_ops = { -+ .alloc_inode = squashfs_alloc_inode, -+ .destroy_inode = squashfs_destroy_inode, -+ .statfs = squashfs_statfs, -+ .put_super = squashfs_put_super, -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_symlink_aops = { -+ .readpage = squashfs_symlink_readpage -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_aops = { -+ .readpage = squashfs_readpage -+}; -+ -+SQSH_EXTERN struct address_space_operations squashfs_aops_4K = { -+ .readpage = squashfs_readpage4K -+}; -+ -+static struct file_operations squashfs_dir_ops = { -+ .read = generic_read_dir, -+ .readdir = squashfs_readdir -+}; -+ -+SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = { -+ .lookup = squashfs_lookup -+}; -+ -+ -+static struct buffer_head *get_block_length(struct super_block *s, -+ int *cur_index, int *offset, int *c_byte) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ unsigned short temp; -+ struct buffer_head *bh; -+ -+ if (!(bh = sb_bread(s, *cur_index))) -+ goto out; -+ -+ if (msblk->devblksize - *offset == 1) { -+ if (msblk->swap) -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ else -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ brelse(bh); -+ if (!(bh = sb_bread(s, ++(*cur_index)))) -+ goto out; -+ if (msblk->swap) -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ bh->b_data); -+ else -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ bh->b_data); -+ *c_byte = temp; -+ *offset = 1; -+ } else { -+ if (msblk->swap) { -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset + 1)); -+ } else { -+ ((unsigned char *) &temp)[0] = *((unsigned char *) -+ (bh->b_data + *offset)); -+ ((unsigned char *) &temp)[1] = *((unsigned char *) -+ (bh->b_data + *offset + 1)); -+ } -+ *c_byte = temp; -+ *offset += 2; -+ } -+ -+ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) { -+ if (*offset == msblk->devblksize) { -+ brelse(bh); -+ if (!(bh = sb_bread(s, ++(*cur_index)))) -+ goto out; -+ *offset = 0; -+ } -+ if (*((unsigned char *) (bh->b_data + *offset)) != -+ SQUASHFS_MARKER_BYTE) { -+ ERROR("Metadata block marker corrupt @ %x\n", -+ *cur_index); -+ brelse(bh); -+ goto out; -+ } -+ (*offset)++; -+ } -+ return bh; -+ -+out: -+ return NULL; -+} -+ -+ -+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer, -+ long long index, unsigned int length, -+ long long *next_index) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> -+ msblk->devblksize_log2) + 2]; -+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1); -+ unsigned int cur_index = index >> msblk->devblksize_log2; -+ int bytes, avail_bytes, b = 0, k; -+ char *c_buffer; -+ unsigned int compressed; -+ unsigned int c_byte = length; -+ -+ if (c_byte) { -+ bytes = msblk->devblksize - offset; -+ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte); -+ c_buffer = compressed ? msblk->read_data : buffer; -+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte); -+ -+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed -+ ? "" : "un", (unsigned int) c_byte); -+ -+ if (!(bh[0] = sb_getblk(s, cur_index))) -+ goto block_release; -+ -+ for (b = 1; bytes < c_byte; b++) { -+ if (!(bh[b] = sb_getblk(s, ++cur_index))) -+ goto block_release; -+ bytes += msblk->devblksize; -+ } -+ ll_rw_block(READ, b, bh); -+ } else { -+ if (!(bh[0] = get_block_length(s, &cur_index, &offset, -+ &c_byte))) -+ goto read_failure; -+ -+ bytes = msblk->devblksize - offset; -+ compressed = SQUASHFS_COMPRESSED(c_byte); -+ c_buffer = compressed ? msblk->read_data : buffer; -+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte); -+ -+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed -+ ? "" : "un", (unsigned int) c_byte); -+ -+ for (b = 1; bytes < c_byte; b++) { -+ if (!(bh[b] = sb_getblk(s, ++cur_index))) -+ goto block_release; -+ bytes += msblk->devblksize; -+ } -+ ll_rw_block(READ, b - 1, bh + 1); -+ } -+ -+ if (compressed) -+ down(&msblk->read_data_mutex); -+ -+ for (bytes = 0, k = 0; k < b; k++) { -+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ? -+ msblk->devblksize - offset : -+ c_byte - bytes; -+ wait_on_buffer(bh[k]); -+ if (!buffer_uptodate(bh[k])) -+ goto block_release; -+ memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes); -+ bytes += avail_bytes; -+ offset = 0; -+ brelse(bh[k]); -+ } -+ -+ /* -+ * uncompress block -+ */ -+ if (compressed) { -+ int zlib_err; -+ -+ stream.next_in = c_buffer; -+ stream.avail_in = c_byte; -+ stream.next_out = buffer; -+ stream.avail_out = msblk->read_size; -+ -+ if (((zlib_err = zlib_inflateInit(&stream)) != Z_OK) || -+ ((zlib_err = zlib_inflate(&stream, Z_FINISH)) -+ != Z_STREAM_END) || ((zlib_err = -+ zlib_inflateEnd(&stream)) != Z_OK)) { -+ ERROR("zlib_fs returned unexpected result 0x%x\n", -+ zlib_err); -+ bytes = 0; -+ } else -+ bytes = stream.total_out; -+ -+ up(&msblk->read_data_mutex); -+ } -+ -+ if (next_index) -+ *next_index = index + c_byte + (length ? 0 : -+ (SQUASHFS_CHECK_DATA(msblk->sblk.flags) -+ ? 3 : 2)); -+ return bytes; -+ -+block_release: -+ while (--b >= 0) -+ brelse(bh[b]); -+ -+read_failure: -+ ERROR("sb_bread failed reading block 0x%x\n", cur_index); -+ return 0; -+} -+ -+ -+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer, -+ long long block, unsigned int offset, -+ int length, long long *next_block, -+ unsigned int *next_offset) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ int n, i, bytes, return_length = length; -+ long long next_index; -+ -+ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset); -+ -+ while ( 1 ) { -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ if (msblk->block_cache[i].block == block) -+ break; -+ -+ down(&msblk->block_cache_mutex); -+ -+ if (i == SQUASHFS_CACHED_BLKS) { -+ /* read inode header block */ -+ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS; -+ n ; n --, i = (i + 1) % -+ SQUASHFS_CACHED_BLKS) -+ if (msblk->block_cache[i].block != -+ SQUASHFS_USED_BLK) -+ break; -+ -+ if (n == 0) { -+ wait_queue_t wait; -+ -+ init_waitqueue_entry(&wait, current); -+ add_wait_queue(&msblk->waitq, &wait); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ up(&msblk->block_cache_mutex); -+ schedule(); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&msblk->waitq, &wait); -+ continue; -+ } -+ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS; -+ -+ if (msblk->block_cache[i].block == -+ SQUASHFS_INVALID_BLK) { -+ if (!(msblk->block_cache[i].data = -+ kmalloc(SQUASHFS_METADATA_SIZE, -+ GFP_KERNEL))) { -+ ERROR("Failed to allocate cache" -+ "block\n"); -+ up(&msblk->block_cache_mutex); -+ goto out; -+ } -+ } -+ -+ msblk->block_cache[i].block = SQUASHFS_USED_BLK; -+ up(&msblk->block_cache_mutex); -+ -+ if (!(msblk->block_cache[i].length = -+ squashfs_read_data(s, -+ msblk->block_cache[i].data, -+ block, 0, &next_index))) { -+ ERROR("Unable to read cache block [%llx:%x]\n", -+ block, offset); -+ goto out; -+ } -+ -+ down(&msblk->block_cache_mutex); -+ wake_up(&msblk->waitq); -+ msblk->block_cache[i].block = block; -+ msblk->block_cache[i].next_index = next_index; -+ TRACE("Read cache block [%llx:%x]\n", block, offset); -+ } -+ -+ if (msblk->block_cache[i].block != block) { -+ up(&msblk->block_cache_mutex); -+ continue; -+ } -+ -+ if ((bytes = msblk->block_cache[i].length - offset) >= length) { -+ if (buffer) -+ memcpy(buffer, msblk->block_cache[i].data + -+ offset, length); -+ if (msblk->block_cache[i].length - offset == length) { -+ *next_block = msblk->block_cache[i].next_index; -+ *next_offset = 0; -+ } else { -+ *next_block = block; -+ *next_offset = offset + length; -+ } -+ up(&msblk->block_cache_mutex); -+ goto finish; -+ } else { -+ if (buffer) { -+ memcpy(buffer, msblk->block_cache[i].data + -+ offset, bytes); -+ buffer += bytes; -+ } -+ block = msblk->block_cache[i].next_index; -+ up(&msblk->block_cache_mutex); -+ length -= bytes; -+ offset = 0; -+ } -+ } -+ -+finish: -+ return return_length; -+out: -+ return 0; -+} -+ -+ -+static int get_fragment_location(struct super_block *s, unsigned int fragment, -+ long long *fragment_start_block, -+ unsigned int *fragment_size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ long long start_block = -+ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)]; -+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); -+ struct squashfs_fragment_entry fragment_entry; -+ -+ if (msblk->swap) { -+ struct squashfs_fragment_entry sfragment_entry; -+ -+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, -+ start_block, offset, -+ sizeof(sfragment_entry), &start_block, -+ &offset)) -+ goto out; -+ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry, -+ start_block, offset, -+ sizeof(fragment_entry), &start_block, -+ &offset)) -+ goto out; -+ -+ *fragment_start_block = fragment_entry.start_block; -+ *fragment_size = fragment_entry.size; -+ -+ return 1; -+ -+out: -+ return 0; -+} -+ -+ -+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct -+ squashfs_fragment_cache *fragment) -+{ -+ down(&msblk->fragment_mutex); -+ fragment->locked --; -+ wake_up(&msblk->fragment_wait_queue); -+ up(&msblk->fragment_mutex); -+} -+ -+ -+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block -+ *s, long long start_block, -+ int length) -+{ -+ int i, n; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ -+ while ( 1 ) { -+ down(&msblk->fragment_mutex); -+ -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS && -+ msblk->fragment[i].block != start_block; i++); -+ -+ if (i == SQUASHFS_CACHED_FRAGMENTS) { -+ for (i = msblk->next_fragment, n = -+ SQUASHFS_CACHED_FRAGMENTS; n && -+ msblk->fragment[i].locked; n--, i = (i + 1) % -+ SQUASHFS_CACHED_FRAGMENTS); -+ -+ if (n == 0) { -+ wait_queue_t wait; -+ -+ init_waitqueue_entry(&wait, current); -+ add_wait_queue(&msblk->fragment_wait_queue, -+ &wait); -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ up(&msblk->fragment_mutex); -+ schedule(); -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&msblk->fragment_wait_queue, -+ &wait); -+ continue; -+ } -+ msblk->next_fragment = (msblk->next_fragment + 1) % -+ SQUASHFS_CACHED_FRAGMENTS; -+ -+ if (msblk->fragment[i].data == NULL) -+ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC -+ (SQUASHFS_FILE_MAX_SIZE))) { -+ ERROR("Failed to allocate fragment " -+ "cache block\n"); -+ up(&msblk->fragment_mutex); -+ goto out; -+ } -+ -+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK; -+ msblk->fragment[i].locked = 1; -+ up(&msblk->fragment_mutex); -+ -+ if (!(msblk->fragment[i].length = squashfs_read_data(s, -+ msblk->fragment[i].data, -+ start_block, length, NULL))) { -+ ERROR("Unable to read fragment cache block " -+ "[%llx]\n", start_block); -+ msblk->fragment[i].locked = 0; -+ goto out; -+ } -+ -+ msblk->fragment[i].block = start_block; -+ TRACE("New fragment %d, start block %lld, locked %d\n", -+ i, msblk->fragment[i].block, -+ msblk->fragment[i].locked); -+ break; -+ } -+ -+ msblk->fragment[i].locked++; -+ up(&msblk->fragment_mutex); -+ TRACE("Got fragment %d, start block %lld, locked %d\n", i, -+ msblk->fragment[i].block, -+ msblk->fragment[i].locked); -+ break; -+ } -+ -+ return &msblk->fragment[i]; -+ -+out: -+ return NULL; -+} -+ -+ -+static struct inode *squashfs_new_inode(struct super_block *s, -+ struct squashfs_base_inode_header *inodeb) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct inode *i = new_inode(s); -+ -+ if (i) { -+ i->i_ino = inodeb->inode_number; -+ i->i_mtime.tv_sec = inodeb->mtime; -+ i->i_atime.tv_sec = inodeb->mtime; -+ i->i_ctime.tv_sec = inodeb->mtime; -+ i->i_uid = msblk->uid[inodeb->uid]; -+ i->i_mode = inodeb->mode; -+ i->i_size = 0; -+ if (inodeb->guid == SQUASHFS_GUIDS) -+ i->i_gid = i->i_uid; -+ else -+ i->i_gid = msblk->guid[inodeb->guid]; -+ } -+ -+ return i; -+} -+ -+ -+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode) -+{ -+ struct inode *i; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long block = SQUASHFS_INODE_BLK(inode) + -+ sblk->inode_table_start; -+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode); -+ long long next_block; -+ unsigned int next_offset; -+ union squashfs_inode_header id, sid; -+ struct squashfs_base_inode_header *inodeb = &id.base, -+ *sinodeb = &sid.base; -+ -+ TRACE("Entered squashfs_iget\n"); -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block, -+ offset, sizeof(*sinodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb, -+ sizeof(*sinodeb)); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) inodeb, block, -+ offset, sizeof(*inodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ switch(inodeb->inode_type) { -+ case SQUASHFS_FILE_TYPE: { -+ unsigned int frag_size; -+ long long frag_blk; -+ struct squashfs_reg_inode_header *inodep = &id.reg; -+ struct squashfs_reg_inode_header *sinodep = &sid.reg; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = 1; -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %llx, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_LREG_TYPE: { -+ unsigned int frag_size; -+ long long frag_blk; -+ struct squashfs_lreg_inode_header *inodep = &id.lreg; -+ struct squashfs_lreg_inode_header *sinodep = &sid.lreg; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %llx, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_DIR_TYPE: { -+ struct squashfs_dir_inode_header *inodep = &id.dir; -+ struct squashfs_dir_inode_header *sinodep = &sid.dir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops; -+ i->i_fop = &squashfs_dir_ops; -+ i->i_mode |= S_IFDIR; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = 0; -+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; -+ -+ TRACE("Directory inode %x:%x, start_block %x, offset " -+ "%x\n", SQUASHFS_INODE_BLK(inode), -+ offset, inodep->start_block, -+ inodep->offset); -+ break; -+ } -+ case SQUASHFS_LDIR_TYPE: { -+ struct squashfs_ldir_inode_header *inodep = &id.ldir; -+ struct squashfs_ldir_inode_header *sinodep = &sid.ldir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops; -+ i->i_fop = &squashfs_dir_ops; -+ i->i_mode |= S_IFDIR; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block; -+ SQUASHFS_I(i)->u.s2.directory_index_offset = -+ next_offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = -+ inodep->i_count; -+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode; -+ -+ TRACE("Long directory inode %x:%x, start_block %x, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, inodep->offset); -+ break; -+ } -+ case SQUASHFS_SYMLINK_TYPE: { -+ struct squashfs_symlink_inode_header *inodep = -+ &id.symlink; -+ struct squashfs_symlink_inode_header *sinodep = -+ &sid.symlink; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_size = inodep->symlink_size; -+ i->i_op = &page_symlink_inode_operations; -+ i->i_data.a_ops = &squashfs_symlink_aops; -+ i->i_mode |= S_IFLNK; -+ SQUASHFS_I(i)->start_block = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ -+ TRACE("Symbolic link inode %x:%x, start_block %llx, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ next_block, next_offset); -+ break; -+ } -+ case SQUASHFS_BLKDEV_TYPE: -+ case SQUASHFS_CHRDEV_TYPE: { -+ struct squashfs_dev_inode_header *inodep = &id.dev; -+ struct squashfs_dev_inode_header *sinodep = &sid.dev; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_mode |= (inodeb->inode_type == -+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : -+ S_IFBLK; -+ init_special_inode(i, i->i_mode, -+ old_decode_dev(inodep->rdev)); -+ -+ TRACE("Device inode %x:%x, rdev %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->rdev); -+ break; -+ } -+ case SQUASHFS_FIFO_TYPE: -+ case SQUASHFS_SOCKET_TYPE: { -+ struct squashfs_ipc_inode_header *inodep = &id.ipc; -+ struct squashfs_ipc_inode_header *sinodep = &sid.ipc; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb)) == NULL) -+ goto failed_read1; -+ -+ i->i_nlink = inodep->nlink; -+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) -+ ? S_IFIFO : S_IFSOCK; -+ init_special_inode(i, i->i_mode, 0); -+ break; -+ } -+ default: -+ ERROR("Unknown inode type %d in squashfs_iget!\n", -+ inodeb->inode_type); -+ goto failed_read1; -+ } -+ -+ insert_inode_hash(i); -+ return i; -+ -+failed_read: -+ ERROR("Unable to read inode [%llx:%x]\n", block, offset); -+ -+failed_read1: -+ return NULL; -+} -+ -+ -+static int read_fragment_index_table(struct super_block *s) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ /* Allocate fragment index table */ -+ if (!(msblk->fragment_index = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES -+ (sblk->fragments), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ return 0; -+ } -+ -+ if (SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments) && -+ !squashfs_read_data(s, (char *) -+ msblk->fragment_index, -+ sblk->fragment_table_start, -+ SQUASHFS_FRAGMENT_INDEX_BYTES -+ (sblk->fragments) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read fragment index table\n"); -+ return 0; -+ } -+ -+ if (msblk->swap) { -+ int i; -+ long long fragment; -+ -+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); -+ i++) { -+ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), -+ &msblk->fragment_index[i], 1); -+ msblk->fragment_index[i] = fragment; -+ } -+ } -+ -+ return 1; -+} -+ -+ -+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent) -+{ -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ msblk->iget = squashfs_iget; -+ msblk->read_blocklist = read_blocklist; -+ msblk->read_fragment_index_table = read_fragment_index_table; -+ -+ if (sblk->s_major == 1) { -+ if (!squashfs_1_0_supported(msblk)) { -+ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems " -+ "are unsupported\n"); -+ SERROR("Please recompile with " -+ "Squashfs 1.0 support enabled\n"); -+ return 0; -+ } -+ } else if (sblk->s_major == 2) { -+ if (!squashfs_2_0_supported(msblk)) { -+ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems " -+ "are unsupported\n"); -+ SERROR("Please recompile with " -+ "Squashfs 2.0 support enabled\n"); -+ return 0; -+ } -+ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor > -+ SQUASHFS_MINOR) { -+ SERROR("Major/Minor mismatch, trying to mount newer %d.%d " -+ "filesystem\n", sblk->s_major, sblk->s_minor); -+ SERROR("Please update your kernel\n"); -+ return 0; -+ } -+ -+ return 1; -+} -+ -+ -+static int squashfs_fill_super(struct super_block *s, void *data, int silent) -+{ -+ struct squashfs_sb_info *msblk; -+ struct squashfs_super_block *sblk; -+ int i; -+ char b[BDEVNAME_SIZE]; -+ struct inode *root; -+ -+ TRACE("Entered squashfs_read_superblock\n"); -+ -+ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info), -+ GFP_KERNEL))) { -+ ERROR("Failed to allocate superblock\n"); -+ goto failure; -+ } -+ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info)); -+ msblk = s->s_fs_info; -+ sblk = &msblk->sblk; -+ -+ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE); -+ msblk->devblksize_log2 = ffz(~msblk->devblksize); -+ -+ init_MUTEX(&msblk->read_data_mutex); -+ init_MUTEX(&msblk->read_page_mutex); -+ init_MUTEX(&msblk->block_cache_mutex); -+ init_MUTEX(&msblk->fragment_mutex); -+ init_MUTEX(&msblk->meta_index_mutex); -+ -+ init_waitqueue_head(&msblk->waitq); -+ init_waitqueue_head(&msblk->fragment_wait_queue); -+ -+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START, -+ sizeof(struct squashfs_super_block) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ SERROR("unable to read superblock\n"); -+ goto failed_mount; -+ } -+ -+ /* Check it is a SQUASHFS superblock */ -+ msblk->swap = 0; -+ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) { -+ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) { -+ struct squashfs_super_block ssblk; -+ -+ WARNING("Mounting a different endian SQUASHFS " -+ "filesystem on %s\n", bdevname(s->s_bdev, b)); -+ -+ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk); -+ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block)); -+ msblk->swap = 1; -+ } else { -+ SERROR("Can't find a SQUASHFS superblock on %s\n", -+ bdevname(s->s_bdev, b)); -+ goto failed_mount; -+ } -+ } -+ -+ /* Check the MAJOR & MINOR versions */ -+ if(!supported_squashfs_filesystem(msblk, silent)) -+ goto failed_mount; -+ -+ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b)); -+ TRACE("Inodes are %scompressed\n", -+ SQUASHFS_UNCOMPRESSED_INODES -+ (sblk->flags) ? "un" : ""); -+ TRACE("Data is %scompressed\n", -+ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags) -+ ? "un" : ""); -+ TRACE("Check data is %s present in the filesystem\n", -+ SQUASHFS_CHECK_DATA(sblk->flags) ? -+ "" : "not"); -+ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used); -+ TRACE("Block size %d\n", sblk->block_size); -+ TRACE("Number of inodes %d\n", sblk->inodes); -+ if (sblk->s_major > 1) -+ TRACE("Number of fragments %d\n", sblk->fragments); -+ TRACE("Number of uids %d\n", sblk->no_uids); -+ TRACE("Number of gids %d\n", sblk->no_guids); -+ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start); -+ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start); -+ if (sblk->s_major > 1) -+ TRACE("sblk->fragment_table_start %llx\n", -+ sblk->fragment_table_start); -+ TRACE("sblk->uid_start %llx\n", sblk->uid_start); -+ -+ s->s_flags |= MS_RDONLY; -+ s->s_op = &squashfs_ops; -+ -+ /* Init inode_table block pointer array */ -+ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) * -+ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) { -+ ERROR("Failed to allocate block cache\n"); -+ goto failed_mount; -+ } -+ -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK; -+ -+ msblk->next_cache = 0; -+ -+ /* Allocate read_data block */ -+ msblk->read_size = (sblk->block_size < SQUASHFS_METADATA_SIZE) ? -+ SQUASHFS_METADATA_SIZE : -+ sblk->block_size; -+ -+ if (!(msblk->read_data = kmalloc(msblk->read_size, GFP_KERNEL))) { -+ ERROR("Failed to allocate read_data block\n"); -+ goto failed_mount; -+ } -+ -+ /* Allocate read_page block */ -+ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) { -+ ERROR("Failed to allocate read_page block\n"); -+ goto failed_mount; -+ } -+ -+ /* Allocate uid and gid tables */ -+ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ goto failed_mount; -+ } -+ msblk->guid = msblk->uid + sblk->no_uids; -+ -+ if (msblk->swap) { -+ unsigned int suid[sblk->no_uids + sblk->no_guids]; -+ -+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start, -+ ((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int)) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read uid/gid table\n"); -+ goto failed_mount; -+ } -+ -+ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids + -+ sblk->no_guids), (sizeof(unsigned int) * 8)); -+ } else -+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start, -+ ((sblk->no_uids + sblk->no_guids) * -+ sizeof(unsigned int)) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read uid/gid table\n"); -+ goto failed_mount; -+ } -+ -+ -+ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk)) -+ goto allocate_root; -+ -+ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) * -+ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) { -+ ERROR("Failed to allocate fragment block cache\n"); -+ goto failed_mount; -+ } -+ -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) { -+ msblk->fragment[i].locked = 0; -+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK; -+ msblk->fragment[i].data = NULL; -+ } -+ -+ msblk->next_fragment = 0; -+ -+ /* Allocate fragment index table */ -+ if (msblk->read_fragment_index_table(s) == 0) -+ goto failed_mount; -+ -+allocate_root: -+ if ((root = (msblk->iget)(s, sblk->root_inode)) == NULL) -+ goto failed_mount; -+ -+ if ((s->s_root = d_alloc_root(root)) == NULL) { -+ ERROR("Root inode create failed\n"); -+ iput(root); -+ goto failed_mount; -+ } -+ -+ TRACE("Leaving squashfs_read_super\n"); -+ return 0; -+ -+failed_mount: -+ kfree(msblk->fragment_index); -+ kfree(msblk->fragment); -+ kfree(msblk->uid); -+ kfree(msblk->read_page); -+ kfree(msblk->read_data); -+ kfree(msblk->block_cache); -+ kfree(msblk->fragment_index_2); -+ kfree(s->s_fs_info); -+ s->s_fs_info = NULL; -+ return -EINVAL; -+ -+failure: -+ return -ENOMEM; -+} -+ -+ -+static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) -+{ -+ struct squashfs_sb_info *msblk = dentry->d_inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ TRACE("Entered squashfs_statfs\n"); -+ -+ buf->f_type = SQUASHFS_MAGIC; -+ buf->f_bsize = sblk->block_size; -+ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1; -+ buf->f_bfree = buf->f_bavail = 0; -+ buf->f_files = sblk->inodes; -+ buf->f_ffree = 0; -+ buf->f_namelen = SQUASHFS_NAME_LEN; -+ -+ return 0; -+} -+ -+ -+static int squashfs_symlink_readpage(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ int index = page->index << PAGE_CACHE_SHIFT, length, bytes; -+ long long block = SQUASHFS_I(inode)->start_block; -+ int offset = SQUASHFS_I(inode)->offset; -+ void *pageaddr = kmap(page); -+ -+ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block " -+ "%llx, offset %x\n", page->index, -+ SQUASHFS_I(inode)->start_block, -+ SQUASHFS_I(inode)->offset); -+ -+ for (length = 0; length < index; length += bytes) { -+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, -+ block, offset, PAGE_CACHE_SIZE, &block, -+ &offset))) { -+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, -+ offset); -+ goto skip_read; -+ } -+ } -+ -+ if (length != index) { -+ ERROR("(squashfs_symlink_readpage) length != index\n"); -+ bytes = 0; -+ goto skip_read; -+ } -+ -+ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : -+ i_size_read(inode) - length; -+ -+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, -+ offset, bytes, &block, &offset))) -+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset); -+ -+skip_read: -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset) -+{ -+ struct meta_index *meta = NULL; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ int i; -+ -+ down(&msblk->meta_index_mutex); -+ -+ TRACE("locate_meta_index: index %d, offset %d\n", index, offset); -+ -+ if(msblk->meta_index == NULL) -+ goto not_allocated; -+ -+ for (i = 0; i < SQUASHFS_META_NUMBER; i ++) -+ if (msblk->meta_index[i].inode_number == inode->i_ino && -+ msblk->meta_index[i].offset >= offset && -+ msblk->meta_index[i].offset <= index && -+ msblk->meta_index[i].locked == 0) { -+ TRACE("locate_meta_index: entry %d, offset %d\n", i, -+ msblk->meta_index[i].offset); -+ meta = &msblk->meta_index[i]; -+ offset = meta->offset; -+ } -+ -+ if (meta) -+ meta->locked = 1; -+ -+not_allocated: -+ up(&msblk->meta_index_mutex); -+ -+ return meta; -+} -+ -+ -+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip) -+{ -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct meta_index *meta = NULL; -+ int i; -+ -+ down(&msblk->meta_index_mutex); -+ -+ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip); -+ -+ if(msblk->meta_index == NULL) { -+ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) * -+ SQUASHFS_META_NUMBER, GFP_KERNEL))) { -+ ERROR("Failed to allocate meta_index\n"); -+ goto failed; -+ } -+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) { -+ msblk->meta_index[i].inode_number = 0; -+ msblk->meta_index[i].locked = 0; -+ } -+ msblk->next_meta_index = 0; -+ } -+ -+ for(i = SQUASHFS_META_NUMBER; i && -+ msblk->meta_index[msblk->next_meta_index].locked; i --) -+ msblk->next_meta_index = (msblk->next_meta_index + 1) % -+ SQUASHFS_META_NUMBER; -+ -+ if(i == 0) { -+ TRACE("empty_meta_index: failed!\n"); -+ goto failed; -+ } -+ -+ TRACE("empty_meta_index: returned meta entry %d, %p\n", -+ msblk->next_meta_index, -+ &msblk->meta_index[msblk->next_meta_index]); -+ -+ meta = &msblk->meta_index[msblk->next_meta_index]; -+ msblk->next_meta_index = (msblk->next_meta_index + 1) % -+ SQUASHFS_META_NUMBER; -+ -+ meta->inode_number = inode->i_ino; -+ meta->offset = offset; -+ meta->skip = skip; -+ meta->entries = 0; -+ meta->locked = 1; -+ -+failed: -+ up(&msblk->meta_index_mutex); -+ return meta; -+} -+ -+ -+void release_meta_index(struct inode *inode, struct meta_index *meta) -+{ -+ meta->locked = 0; -+} -+ -+ -+static int read_block_index(struct super_block *s, int blocks, char *block_list, -+ long long *start_block, int *offset) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ unsigned int *block_listp; -+ int block = 0; -+ -+ if (msblk->swap) { -+ char sblock_list[blocks << 2]; -+ -+ if (!squashfs_get_cached_block(s, sblock_list, *start_block, -+ *offset, blocks << 2, start_block, offset)) { -+ ERROR("Unable to read block list [%llx:%x]\n", -+ *start_block, *offset); -+ goto failure; -+ } -+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list), -+ ((unsigned int *)sblock_list), blocks); -+ } else -+ if (!squashfs_get_cached_block(s, block_list, *start_block, -+ *offset, blocks << 2, start_block, offset)) { -+ ERROR("Unable to read block list [%llx:%x]\n", -+ *start_block, *offset); -+ goto failure; -+ } -+ -+ for (block_listp = (unsigned int *) block_list; blocks; -+ block_listp++, blocks --) -+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp); -+ -+ return block; -+ -+failure: -+ return -1; -+} -+ -+ -+#define SIZE 256 -+ -+static inline int calculate_skip(int blocks) { -+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES); -+ return skip >= 7 ? 7 : skip + 1; -+} -+ -+ -+static int get_meta_index(struct inode *inode, int index, -+ long long *index_block, int *index_offset, -+ long long *data_block, char *block_list) -+{ -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log); -+ int offset = 0; -+ struct meta_index *meta; -+ struct meta_entry *meta_entry; -+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start; -+ int cur_offset = SQUASHFS_I(inode)->offset; -+ long long cur_data_block = SQUASHFS_I(inode)->start_block; -+ int i; -+ -+ index /= SQUASHFS_META_INDEXES * skip; -+ -+ while ( offset < index ) { -+ meta = locate_meta_index(inode, index, offset + 1); -+ -+ if (meta == NULL) { -+ if ((meta = empty_meta_index(inode, offset + 1, -+ skip)) == NULL) -+ goto all_done; -+ } else { -+ offset = index < meta->offset + meta->entries ? index : -+ meta->offset + meta->entries - 1; -+ meta_entry = &meta->meta_entry[offset - meta->offset]; -+ cur_index_block = meta_entry->index_block + sblk->inode_table_start; -+ cur_offset = meta_entry->offset; -+ cur_data_block = meta_entry->data_block; -+ TRACE("get_meta_index: offset %d, meta->offset %d, " -+ "meta->entries %d\n", offset, meta->offset, -+ meta->entries); -+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x" -+ " data_block 0x%llx\n", cur_index_block, -+ cur_offset, cur_data_block); -+ } -+ -+ for (i = meta->offset + meta->entries; i <= index && -+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) { -+ int blocks = skip * SQUASHFS_META_INDEXES; -+ -+ while (blocks) { -+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) : -+ blocks; -+ int res = read_block_index(inode->i_sb, block, -+ block_list, &cur_index_block, -+ &cur_offset); -+ -+ if (res == -1) -+ goto failed; -+ -+ cur_data_block += res; -+ blocks -= block; -+ } -+ -+ meta_entry = &meta->meta_entry[i - meta->offset]; -+ meta_entry->index_block = cur_index_block - sblk->inode_table_start; -+ meta_entry->offset = cur_offset; -+ meta_entry->data_block = cur_data_block; -+ meta->entries ++; -+ offset ++; -+ } -+ -+ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n", -+ meta->offset, meta->entries); -+ -+ release_meta_index(inode, meta); -+ } -+ -+all_done: -+ *index_block = cur_index_block; -+ *index_offset = cur_offset; -+ *data_block = cur_data_block; -+ -+ return offset * SQUASHFS_META_INDEXES * skip; -+ -+failed: -+ release_meta_index(inode, meta); -+ return -1; -+} -+ -+ -+static long long read_blocklist(struct inode *inode, int index, -+ int readahead_blks, char *block_list, -+ unsigned short **block_p, unsigned int *bsize) -+{ -+ long long block_ptr; -+ int offset; -+ long long block; -+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block, -+ block_list); -+ -+ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset" -+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset, -+ block); -+ -+ if(res == -1) -+ goto failure; -+ -+ index -= res; -+ -+ while ( index ) { -+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index; -+ int res = read_block_index(inode->i_sb, blocks, block_list, -+ &block_ptr, &offset); -+ if (res == -1) -+ goto failure; -+ block += res; -+ index -= blocks; -+ } -+ -+ if (read_block_index(inode->i_sb, 1, block_list, -+ &block_ptr, &offset) == -1) -+ goto failure; -+ *bsize = *((unsigned int *) block_list); -+ -+ return block; -+ -+failure: -+ return 0; -+} -+ -+ -+static int squashfs_readpage(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned char block_list[SIZE]; -+ long long block; -+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0; -+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT); -+ void *pageaddr; -+ struct squashfs_fragment_cache *fragment = NULL; -+ char *data_ptr = msblk->read_page; -+ -+ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1; -+ int start_index = page->index & ~mask; -+ int end_index = start_index | mask; -+ -+ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n", -+ page->index, -+ SQUASHFS_I(inode)->start_block); -+ -+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> -+ PAGE_CACHE_SHIFT)) -+ goto skip_read; -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || index < (i_size_read(inode) >> -+ sblk->block_log)) { -+ if ((block = (msblk->read_blocklist)(inode, index, 1, -+ block_list, NULL, &bsize)) == 0) -+ goto skip_read; -+ -+ down(&msblk->read_page_mutex); -+ -+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page, -+ block, bsize, NULL))) { -+ ERROR("Unable to read page, block %llx, size %x\n", block, -+ bsize); -+ up(&msblk->read_page_mutex); -+ goto skip_read; -+ } -+ } else { -+ if ((fragment = get_cached_fragment(inode->i_sb, -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ SQUASHFS_I(inode)->u.s1.fragment_size)) -+ == NULL) { -+ ERROR("Unable to read page, block %llx, size %x\n", -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ (int) SQUASHFS_I(inode)-> -+ u.s1.fragment_size); -+ goto skip_read; -+ } -+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset + -+ (i_size_read(inode) & (sblk->block_size -+ - 1)); -+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset; -+ data_ptr = fragment->data; -+ } -+ -+ for (i = start_index; i <= end_index && byte_offset < bytes; -+ i++, byte_offset += PAGE_CACHE_SIZE) { -+ struct page *push_page; -+ int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? -+ PAGE_CACHE_SIZE : bytes - byte_offset; -+ -+ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", -+ bytes, i, byte_offset, available_bytes); -+ -+ if (i == page->index) { -+ pageaddr = kmap_atomic(page, KM_USER0); -+ memcpy(pageaddr, data_ptr + byte_offset, -+ available_bytes); -+ memset(pageaddr + available_bytes, 0, -+ PAGE_CACHE_SIZE - available_bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ } else if ((push_page = -+ grab_cache_page_nowait(page->mapping, i))) { -+ pageaddr = kmap_atomic(push_page, KM_USER0); -+ -+ memcpy(pageaddr, data_ptr + byte_offset, -+ available_bytes); -+ memset(pageaddr + available_bytes, 0, -+ PAGE_CACHE_SIZE - available_bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(push_page); -+ SetPageUptodate(push_page); -+ unlock_page(push_page); -+ page_cache_release(push_page); -+ } -+ } -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || index < (i_size_read(inode) >> -+ sblk->block_log)) -+ up(&msblk->read_page_mutex); -+ else -+ release_cached_fragment(msblk, fragment); -+ -+ return 0; -+ -+skip_read: -+ pageaddr = kmap_atomic(page, KM_USER0); -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+static int squashfs_readpage4K(struct file *file, struct page *page) -+{ -+ struct inode *inode = page->mapping->host; -+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned char block_list[SIZE]; -+ long long block; -+ unsigned int bsize, bytes = 0; -+ void *pageaddr; -+ -+ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n", -+ page->index, -+ SQUASHFS_I(inode)->start_block); -+ -+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> -+ PAGE_CACHE_SHIFT)) { -+ pageaddr = kmap_atomic(page, KM_USER0); -+ goto skip_read; -+ } -+ -+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK -+ || page->index < (i_size_read(inode) >> -+ sblk->block_log)) { -+ block = (msblk->read_blocklist)(inode, page->index, 1, -+ block_list, NULL, &bsize); -+ -+ down(&msblk->read_page_mutex); -+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block, -+ bsize, NULL); -+ pageaddr = kmap_atomic(page, KM_USER0); -+ if (bytes) -+ memcpy(pageaddr, msblk->read_page, bytes); -+ else -+ ERROR("Unable to read page, block %llx, size %x\n", -+ block, bsize); -+ up(&msblk->read_page_mutex); -+ } else { -+ struct squashfs_fragment_cache *fragment = -+ get_cached_fragment(inode->i_sb, -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, -+ SQUASHFS_I(inode)-> u.s1.fragment_size); -+ pageaddr = kmap_atomic(page, KM_USER0); -+ if (fragment) { -+ bytes = i_size_read(inode) & (sblk->block_size - 1); -+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)-> -+ u.s1.fragment_offset, bytes); -+ release_cached_fragment(msblk, fragment); -+ } else -+ ERROR("Unable to read page, block %llx, size %x\n", -+ SQUASHFS_I(inode)-> -+ u.s1.fragment_start_block, (int) -+ SQUASHFS_I(inode)-> u.s1.fragment_size); -+ } -+ -+skip_read: -+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes); -+ kunmap_atomic(pageaddr, KM_USER0); -+ flush_dcache_page(page); -+ SetPageUptodate(page); -+ unlock_page(page); -+ -+ return 0; -+} -+ -+ -+static int get_dir_index_using_offset(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ long long f_pos) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ struct squashfs_dir_index index; -+ -+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", -+ i_count, (unsigned int) f_pos); -+ -+ f_pos =- 3; -+ if (f_pos == 0) -+ goto finish; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) &index, -+ index_start, index_offset, -+ sizeof(index), &index_start, -+ &index_offset); -+ -+ if (index.index > f_pos) -+ break; -+ -+ squashfs_get_cached_block(s, NULL, index_start, index_offset, -+ index.size + 1, &index_start, -+ &index_offset); -+ -+ length = index.index; -+ *next_block = index.start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ -+finish: -+ return length + 3; -+} -+ -+ -+static int get_dir_index_using_name(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ const char *name, int size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ char buffer[sizeof(struct squashfs_dir_index) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_index *index = (struct squashfs_dir_index *) buffer; -+ char str[SQUASHFS_NAME_LEN + 1]; -+ -+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); -+ -+ strncpy(str, name, size); -+ str[size] = '\0'; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX(index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) index, -+ index_start, index_offset, -+ sizeof(struct squashfs_dir_index), -+ &index_start, &index_offset); -+ -+ squashfs_get_cached_block(s, index->name, index_start, -+ index_offset, index->size + 1, -+ &index_start, &index_offset); -+ -+ index->name[index->size + 1] = '\0'; -+ -+ if (strcmp(index->name, str) > 0) -+ break; -+ -+ length = index->index; -+ *next_block = index->start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ return length + 3; -+} -+ -+ -+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir) -+{ -+ struct inode *i = file->f_dentry->d_inode; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, -+ dir_count; -+ struct squashfs_dir_header dirh; -+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; -+ -+ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset); -+ -+ while(file->f_pos < 3) { -+ char *name; -+ int size, i_ino; -+ -+ if(file->f_pos == 0) { -+ name = "."; -+ size = 1; -+ i_ino = i->i_ino; -+ } else { -+ name = ".."; -+ size = 2; -+ i_ino = SQUASHFS_I(i)->u.s2.parent_inode; -+ } -+ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n", -+ (unsigned int) dirent, name, size, (int) -+ file->f_pos, i_ino, -+ squashfs_filetype_table[1]); -+ -+ if (filldir(dirent, name, size, -+ file->f_pos, i_ino, -+ squashfs_filetype_table[1]) < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos += size; -+ dirs_read++; -+ } -+ -+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, -+ file->f_pos); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header sdirh; -+ -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block, next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block, next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, -+ dire->size + 1, &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (file->f_pos >= length) -+ continue; -+ -+ dire->name[dire->size + 1] = '\0'; -+ -+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n", -+ (unsigned int) dirent, dire->name, -+ dire->size + 1, (int) file->f_pos, -+ dirh.start_block, dire->offset, -+ dirh.inode_number + dire->inode_number, -+ squashfs_filetype_table[dire->type]); -+ -+ if (filldir(dirent, dire->name, dire->size + 1, -+ file->f_pos, -+ dirh.inode_number + dire->inode_number, -+ squashfs_filetype_table[dire->type]) -+ < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos = length; -+ dirs_read++; -+ } -+ } -+ -+finish: -+ return dirs_read; -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ return 0; -+} -+ -+ -+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, -+ struct nameidata *nd) -+{ -+ const unsigned char *name = dentry->d_name.name; -+ int len = dentry->d_name.len; -+ struct inode *inode = NULL; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, -+ dir_count; -+ struct squashfs_dir_header dirh; -+ char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN]; -+ struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer; -+ -+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); -+ -+ if (len > SQUASHFS_NAME_LEN) -+ goto exit_loop; -+ -+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, name, -+ len); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header sdirh; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block,next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block,next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, dire->size + 1, -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (name[0] < dire->name[0]) -+ goto exit_loop; -+ -+ if ((len == dire->size + 1) && !strncmp(name, -+ dire->name, len)) { -+ squashfs_inode_t ino = -+ SQUASHFS_MKINODE(dirh.start_block, -+ dire->offset); -+ -+ TRACE("calling squashfs_iget for directory " -+ "entry %s, inode %x:%x, %d\n", name, -+ dirh.start_block, dire->offset, -+ dirh.inode_number + dire->inode_number); -+ -+ inode = (msblk->iget)(i->i_sb, ino); -+ -+ goto exit_loop; -+ } -+ } -+ } -+ -+exit_loop: -+ d_add(dentry, inode); -+ return ERR_PTR(0); -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ goto exit_loop; -+} -+ -+ -+static void squashfs_put_super(struct super_block *s) -+{ -+ int i; -+ -+ if (s->s_fs_info) { -+ struct squashfs_sb_info *sbi = s->s_fs_info; -+ if (sbi->block_cache) -+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++) -+ if (sbi->block_cache[i].block != -+ SQUASHFS_INVALID_BLK) -+ kfree(sbi->block_cache[i].data); -+ if (sbi->fragment) -+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) -+ SQUASHFS_FREE(sbi->fragment[i].data); -+ kfree(sbi->fragment); -+ kfree(sbi->block_cache); -+ kfree(sbi->read_data); -+ kfree(sbi->read_page); -+ kfree(sbi->uid); -+ kfree(sbi->fragment_index); -+ kfree(sbi->fragment_index_2); -+ kfree(sbi->meta_index); -+ kfree(s->s_fs_info); -+ s->s_fs_info = NULL; -+ } -+} -+ -+ -+static int squashfs_get_sb(struct file_system_type *fs_type, -+ int flags, const char *dev_name, void *data, -+ struct vfsmount *mnt) -+{ -+ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super, mnt); -+} -+ -+ -+static int __init init_squashfs_fs(void) -+{ -+ int err = init_inodecache(); -+ if (err) -+ goto out; -+ -+ printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) " -+ "Phillip Lougher\n"); -+ -+ if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { -+ ERROR("Failed to allocate zlib workspace\n"); -+ destroy_inodecache(); -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ if ((err = register_filesystem(&squashfs_fs_type))) { -+ vfree(stream.workspace); -+ destroy_inodecache(); -+ } -+ -+out: -+ return err; -+} -+ -+ -+static void __exit exit_squashfs_fs(void) -+{ -+ vfree(stream.workspace); -+ unregister_filesystem(&squashfs_fs_type); -+ destroy_inodecache(); -+} -+ -+ -+static struct kmem_cache * squashfs_inode_cachep; -+ -+ -+static struct inode *squashfs_alloc_inode(struct super_block *sb) -+{ -+ struct squashfs_inode_info *ei; -+ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL); -+ if (!ei) -+ return NULL; -+ return &ei->vfs_inode; -+} -+ -+ -+static void squashfs_destroy_inode(struct inode *inode) -+{ -+ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode)); -+} -+ -+ -+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) -+{ -+ struct squashfs_inode_info *ei = foo; -+ -+ inode_init_once(&ei->vfs_inode); -+} -+ -+ -+static int __init init_inodecache(void) -+{ -+ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache", -+ sizeof(struct squashfs_inode_info), -+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, -+ init_once, NULL); -+ if (squashfs_inode_cachep == NULL) -+ return -ENOMEM; -+ return 0; -+} -+ -+ -+static void destroy_inodecache(void) -+{ -+ kmem_cache_destroy(squashfs_inode_cachep); -+} -+ -+ -+module_init(init_squashfs_fs); -+module_exit(exit_squashfs_fs); -+MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem"); -+MODULE_AUTHOR("Phillip Lougher "); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/fs/squashfs/Makefile -@@ -0,0 +1,7 @@ -+# -+# Makefile for the linux squashfs routines. -+# -+ -+obj-$(CONFIG_SQUASHFS) += squashfs.o -+squashfs-y += inode.o -+squashfs-y += squashfs2_0.o ---- /dev/null -+++ b/fs/squashfs/squashfs2_0.c -@@ -0,0 +1,758 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs2_0.c -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "squashfs.h" -+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); -+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, -+ struct nameidata *); -+ -+static struct file_operations squashfs_dir_ops_2 = { -+ .read = generic_read_dir, -+ .readdir = squashfs_readdir_2 -+}; -+ -+static struct inode_operations squashfs_dir_inode_ops_2 = { -+ .lookup = squashfs_lookup_2 -+}; -+ -+static unsigned char squashfs_filetype_table[] = { -+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK -+}; -+ -+static int read_fragment_index_table_2(struct super_block *s) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 -+ (sblk->fragments), GFP_KERNEL))) { -+ ERROR("Failed to allocate uid/gid table\n"); -+ return 0; -+ } -+ -+ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && -+ !squashfs_read_data(s, (char *) -+ msblk->fragment_index_2, -+ sblk->fragment_table_start, -+ SQUASHFS_FRAGMENT_INDEX_BYTES_2 -+ (sblk->fragments) | -+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { -+ ERROR("unable to read fragment index table\n"); -+ return 0; -+ } -+ -+ if (msblk->swap) { -+ int i; -+ unsigned int fragment; -+ -+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); -+ i++) { -+ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), -+ &msblk->fragment_index_2[i], 1); -+ msblk->fragment_index_2[i] = fragment; -+ } -+ } -+ -+ return 1; -+} -+ -+ -+static int get_fragment_location_2(struct super_block *s, unsigned int fragment, -+ long long *fragment_start_block, -+ unsigned int *fragment_size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ long long start_block = -+ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; -+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); -+ struct squashfs_fragment_entry_2 fragment_entry; -+ -+ if (msblk->swap) { -+ struct squashfs_fragment_entry_2 sfragment_entry; -+ -+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, -+ start_block, offset, -+ sizeof(sfragment_entry), &start_block, -+ &offset)) -+ goto out; -+ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry, -+ start_block, offset, -+ sizeof(fragment_entry), &start_block, -+ &offset)) -+ goto out; -+ -+ *fragment_start_block = fragment_entry.start_block; -+ *fragment_size = fragment_entry.size; -+ -+ return 1; -+ -+out: -+ return 0; -+} -+ -+ -+static struct inode *squashfs_new_inode(struct super_block *s, -+ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ struct inode *i = new_inode(s); -+ -+ if (i) { -+ i->i_ino = ino; -+ i->i_mtime.tv_sec = sblk->mkfs_time; -+ i->i_atime.tv_sec = sblk->mkfs_time; -+ i->i_ctime.tv_sec = sblk->mkfs_time; -+ i->i_uid = msblk->uid[inodeb->uid]; -+ i->i_mode = inodeb->mode; -+ i->i_nlink = 1; -+ i->i_size = 0; -+ if (inodeb->guid == SQUASHFS_GUIDS) -+ i->i_gid = i->i_uid; -+ else -+ i->i_gid = msblk->guid[inodeb->guid]; -+ } -+ -+ return i; -+} -+ -+ -+static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode) -+{ -+ struct inode *i; -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ unsigned int block = SQUASHFS_INODE_BLK(inode) + -+ sblk->inode_table_start; -+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode); -+ unsigned int ino = SQUASHFS_MK_VFS_INODE(block -+ - sblk->inode_table_start, offset); -+ long long next_block; -+ unsigned int next_offset; -+ union squashfs_inode_header_2 id, sid; -+ struct squashfs_base_inode_header_2 *inodeb = &id.base, -+ *sinodeb = &sid.base; -+ -+ TRACE("Entered squashfs_iget\n"); -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block, -+ offset, sizeof(*sinodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, -+ sizeof(*sinodeb)); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) inodeb, block, -+ offset, sizeof(*inodeb), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ switch(inodeb->inode_type) { -+ case SQUASHFS_FILE_TYPE: { -+ struct squashfs_reg_inode_header_2 *inodep = &id.reg; -+ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; -+ long long frag_blk; -+ unsigned int frag_size; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ frag_blk = SQUASHFS_INVALID_BLK; -+ if (inodep->fragment != SQUASHFS_INVALID_FRAG && -+ !get_fragment_location_2(s, -+ inodep->fragment, &frag_blk, &frag_size)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_fop = &generic_ro_fops; -+ i->i_mode |= S_IFREG; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ i->i_blocks = ((i->i_size - 1) >> 9) + 1; -+ i->i_blksize = PAGE_CACHE_SIZE; -+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; -+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size; -+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->u.s1.block_list_start = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ if (sblk->block_size > 4096) -+ i->i_data.a_ops = &squashfs_aops; -+ else -+ i->i_data.a_ops = &squashfs_aops_4K; -+ -+ TRACE("File inode %x:%x, start_block %x, " -+ "block_list_start %llx, offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, next_block, -+ next_offset); -+ break; -+ } -+ case SQUASHFS_DIR_TYPE: { -+ struct squashfs_dir_inode_header_2 *inodep = &id.dir; -+ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops_2; -+ i->i_fop = &squashfs_dir_ops_2; -+ i->i_mode |= S_IFDIR; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = 0; -+ SQUASHFS_I(i)->u.s2.parent_inode = 0; -+ -+ TRACE("Directory inode %x:%x, start_block %x, offset " -+ "%x\n", SQUASHFS_INODE_BLK(inode), -+ offset, inodep->start_block, -+ inodep->offset); -+ break; -+ } -+ case SQUASHFS_LDIR_TYPE: { -+ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; -+ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->file_size; -+ i->i_op = &squashfs_dir_inode_ops_2; -+ i->i_fop = &squashfs_dir_ops_2; -+ i->i_mode |= S_IFDIR; -+ i->i_mtime.tv_sec = inodep->mtime; -+ i->i_atime.tv_sec = inodep->mtime; -+ i->i_ctime.tv_sec = inodep->mtime; -+ SQUASHFS_I(i)->start_block = inodep->start_block; -+ SQUASHFS_I(i)->offset = inodep->offset; -+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block; -+ SQUASHFS_I(i)->u.s2.directory_index_offset = -+ next_offset; -+ SQUASHFS_I(i)->u.s2.directory_index_count = -+ inodep->i_count; -+ SQUASHFS_I(i)->u.s2.parent_inode = 0; -+ -+ TRACE("Long directory inode %x:%x, start_block %x, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->start_block, inodep->offset); -+ break; -+ } -+ case SQUASHFS_SYMLINK_TYPE: { -+ struct squashfs_symlink_inode_header_2 *inodep = -+ &id.symlink; -+ struct squashfs_symlink_inode_header_2 *sinodep = -+ &sid.symlink; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, -+ sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_size = inodep->symlink_size; -+ i->i_op = &page_symlink_inode_operations; -+ i->i_data.a_ops = &squashfs_symlink_aops; -+ i->i_mode |= S_IFLNK; -+ SQUASHFS_I(i)->start_block = next_block; -+ SQUASHFS_I(i)->offset = next_offset; -+ -+ TRACE("Symbolic link inode %x:%x, start_block %llx, " -+ "offset %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ next_block, next_offset); -+ break; -+ } -+ case SQUASHFS_BLKDEV_TYPE: -+ case SQUASHFS_CHRDEV_TYPE: { -+ struct squashfs_dev_inode_header_2 *inodep = &id.dev; -+ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; -+ -+ if (msblk->swap) { -+ if (!squashfs_get_cached_block(s, (char *) -+ sinodep, block, offset, -+ sizeof(*sinodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); -+ } else -+ if (!squashfs_get_cached_block(s, (char *) -+ inodep, block, offset, -+ sizeof(*inodep), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_mode |= (inodeb->inode_type == -+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : -+ S_IFBLK; -+ init_special_inode(i, i->i_mode, -+ old_decode_dev(inodep->rdev)); -+ -+ TRACE("Device inode %x:%x, rdev %x\n", -+ SQUASHFS_INODE_BLK(inode), offset, -+ inodep->rdev); -+ break; -+ } -+ case SQUASHFS_FIFO_TYPE: -+ case SQUASHFS_SOCKET_TYPE: { -+ if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) -+ goto failed_read1; -+ -+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) -+ ? S_IFIFO : S_IFSOCK; -+ init_special_inode(i, i->i_mode, 0); -+ break; -+ } -+ default: -+ ERROR("Unknown inode type %d in squashfs_iget!\n", -+ inodeb->inode_type); -+ goto failed_read1; -+ } -+ -+ insert_inode_hash(i); -+ return i; -+ -+failed_read: -+ ERROR("Unable to read inode [%x:%x]\n", block, offset); -+ -+failed_read1: -+ return NULL; -+} -+ -+ -+static int get_dir_index_using_offset(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ long long f_pos) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ struct squashfs_dir_index_2 index; -+ -+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", -+ i_count, (unsigned int) f_pos); -+ -+ if (f_pos == 0) -+ goto finish; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index_2 sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) &index, -+ index_start, index_offset, -+ sizeof(index), &index_start, -+ &index_offset); -+ -+ if (index.index > f_pos) -+ break; -+ -+ squashfs_get_cached_block(s, NULL, index_start, index_offset, -+ index.size + 1, &index_start, -+ &index_offset); -+ -+ length = index.index; -+ *next_block = index.start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ -+finish: -+ return length; -+} -+ -+ -+static int get_dir_index_using_name(struct super_block *s, long long -+ *next_block, unsigned int *next_offset, -+ long long index_start, -+ unsigned int index_offset, int i_count, -+ const char *name, int size) -+{ -+ struct squashfs_sb_info *msblk = s->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ int i, length = 0; -+ char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer; -+ char str[SQUASHFS_NAME_LEN + 1]; -+ -+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); -+ -+ strncpy(str, name, size); -+ str[size] = '\0'; -+ -+ for (i = 0; i < i_count; i++) { -+ if (msblk->swap) { -+ struct squashfs_dir_index_2 sindex; -+ squashfs_get_cached_block(s, (char *) &sindex, -+ index_start, index_offset, -+ sizeof(sindex), &index_start, -+ &index_offset); -+ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); -+ } else -+ squashfs_get_cached_block(s, (char *) index, -+ index_start, index_offset, -+ sizeof(struct squashfs_dir_index_2), -+ &index_start, &index_offset); -+ -+ squashfs_get_cached_block(s, index->name, index_start, -+ index_offset, index->size + 1, -+ &index_start, &index_offset); -+ -+ index->name[index->size + 1] = '\0'; -+ -+ if (strcmp(index->name, str) > 0) -+ break; -+ -+ length = index->index; -+ *next_block = index->start_block + sblk->directory_table_start; -+ } -+ -+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; -+ return length; -+} -+ -+ -+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) -+{ -+ struct inode *i = file->f_dentry->d_inode; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, -+ dir_count; -+ struct squashfs_dir_header_2 dirh; -+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; -+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; -+ -+ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); -+ -+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, -+ file->f_pos); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header_2 sdirh; -+ -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry_2 sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block, next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block, next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, -+ dire->size + 1, &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (file->f_pos >= length) -+ continue; -+ -+ dire->name[dire->size + 1] = '\0'; -+ -+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", -+ (unsigned int) dirent, dire->name, -+ dire->size + 1, (int) file->f_pos, -+ dirh.start_block, dire->offset, -+ squashfs_filetype_table[dire->type]); -+ -+ if (filldir(dirent, dire->name, dire->size + 1, -+ file->f_pos, SQUASHFS_MK_VFS_INODE( -+ dirh.start_block, dire->offset), -+ squashfs_filetype_table[dire->type]) -+ < 0) { -+ TRACE("Filldir returned less than 0\n"); -+ goto finish; -+ } -+ file->f_pos = length; -+ dirs_read++; -+ } -+ } -+ -+finish: -+ return dirs_read; -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ return 0; -+} -+ -+ -+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, -+ struct nameidata *nd) -+{ -+ const unsigned char *name = dentry->d_name.name; -+ int len = dentry->d_name.len; -+ struct inode *inode = NULL; -+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ long long next_block = SQUASHFS_I(i)->start_block + -+ sblk->directory_table_start; -+ int next_offset = SQUASHFS_I(i)->offset, length = 0, -+ dir_count; -+ struct squashfs_dir_header_2 dirh; -+ char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN]; -+ struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; -+ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; -+ -+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); -+ -+ if (len > SQUASHFS_NAME_LEN) -+ goto exit_loop; -+ -+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_start, -+ SQUASHFS_I(i)->u.s2.directory_index_offset, -+ SQUASHFS_I(i)->u.s2.directory_index_count, name, -+ len); -+ -+ while (length < i_size_read(i)) { -+ /* read directory header */ -+ if (msblk->swap) { -+ struct squashfs_dir_header_2 sdirh; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, -+ next_block, next_offset, sizeof(sdirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdirh); -+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, -+ next_block, next_offset, sizeof(dirh), -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(dirh); -+ } -+ -+ dir_count = dirh.count + 1; -+ while (dir_count--) { -+ if (msblk->swap) { -+ struct squashfs_dir_entry_2 sdire; -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ &sdire, next_block,next_offset, -+ sizeof(sdire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(sdire); -+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); -+ } else { -+ if (!squashfs_get_cached_block(i->i_sb, (char *) -+ dire, next_block,next_offset, -+ sizeof(*dire), &next_block, -+ &next_offset)) -+ goto failed_read; -+ -+ length += sizeof(*dire); -+ } -+ -+ if (!squashfs_get_cached_block(i->i_sb, dire->name, -+ next_block, next_offset, dire->size + 1, -+ &next_block, &next_offset)) -+ goto failed_read; -+ -+ length += dire->size + 1; -+ -+ if (sorted && name[0] < dire->name[0]) -+ goto exit_loop; -+ -+ if ((len == dire->size + 1) && !strncmp(name, -+ dire->name, len)) { -+ squashfs_inode_t ino = -+ SQUASHFS_MKINODE(dirh.start_block, -+ dire->offset); -+ -+ TRACE("calling squashfs_iget for directory " -+ "entry %s, inode %x:%x, %lld\n", name, -+ dirh.start_block, dire->offset, ino); -+ -+ inode = (msblk->iget)(i->i_sb, ino); -+ -+ goto exit_loop; -+ } -+ } -+ } -+ -+exit_loop: -+ d_add(dentry, inode); -+ return ERR_PTR(0); -+ -+failed_read: -+ ERROR("Unable to read directory block [%llx:%x]\n", next_block, -+ next_offset); -+ goto exit_loop; -+} -+ -+ -+int squashfs_2_0_supported(struct squashfs_sb_info *msblk) -+{ -+ struct squashfs_super_block *sblk = &msblk->sblk; -+ -+ msblk->iget = squashfs_iget_2; -+ msblk->read_fragment_index_table = read_fragment_index_table_2; -+ -+ sblk->bytes_used = sblk->bytes_used_2; -+ sblk->uid_start = sblk->uid_start_2; -+ sblk->guid_start = sblk->guid_start_2; -+ sblk->inode_table_start = sblk->inode_table_start_2; -+ sblk->directory_table_start = sblk->directory_table_start_2; -+ sblk->fragment_table_start = sblk->fragment_table_start_2; -+ -+ return 1; -+} ---- /dev/null -+++ b/fs/squashfs/squashfs.h -@@ -0,0 +1,86 @@ -+/* -+ * Squashfs - a compressed read only filesystem for Linux -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs.h -+ */ -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+#endif -+ -+#ifdef SQUASHFS_TRACE -+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) -+#else -+#define TRACE(s, args...) {} -+#endif -+ -+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) -+ -+#define SERROR(s, args...) do { \ -+ if (!silent) \ -+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\ -+ } while(0) -+ -+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) -+ -+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) -+{ -+ return list_entry(inode, struct squashfs_inode_info, vfs_inode); -+} -+ -+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) -+#define SQSH_EXTERN -+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, -+ long long index, unsigned int length, -+ long long *next_index); -+extern int squashfs_get_cached_block(struct super_block *s, char *buffer, -+ long long block, unsigned int offset, -+ int length, long long *next_block, -+ unsigned int *next_offset); -+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct -+ squashfs_fragment_cache *fragment); -+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block -+ *s, long long start_block, -+ int length); -+extern struct address_space_operations squashfs_symlink_aops; -+extern struct address_space_operations squashfs_aops; -+extern struct address_space_operations squashfs_aops_4K; -+extern struct inode_operations squashfs_dir_inode_ops; -+#else -+#define SQSH_EXTERN static -+#endif -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); -+#else -+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) -+{ -+ return 0; -+} -+#endif -+ -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); -+#else -+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) -+{ -+ return 0; -+} -+#endif ---- a/include/linux/magic.h -+++ b/include/linux/magic.h -@@ -36,6 +36,9 @@ - #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" - #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" - -+#define SQUASHFS_MAGIC 0x73717368 -+#define SQUASHFS_MAGIC_SWAP 0x68737173 -+ - #define SMB_SUPER_MAGIC 0x517B - #define USBDEVICE_SUPER_MAGIC 0x9fa2 - ---- /dev/null -+++ b/include/linux/squashfs_fs.h -@@ -0,0 +1,911 @@ -+#ifndef SQUASHFS_FS -+#define SQUASHFS_FS -+ -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs.h -+ */ -+ -+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#endif -+ -+#ifdef CONFIG_SQUASHFS_VMALLOC -+#define SQUASHFS_ALLOC(a) vmalloc(a) -+#define SQUASHFS_FREE(a) vfree(a) -+#else -+#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL) -+#define SQUASHFS_FREE(a) kfree(a) -+#endif -+#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE -+#define SQUASHFS_MAJOR 3 -+#define SQUASHFS_MINOR 0 -+#define SQUASHFS_START 0 -+ -+/* size of metadata (inode and directory) blocks */ -+#define SQUASHFS_METADATA_SIZE 8192 -+#define SQUASHFS_METADATA_LOG 13 -+ -+/* default size of data blocks */ -+#define SQUASHFS_FILE_SIZE 65536 -+#define SQUASHFS_FILE_LOG 16 -+ -+#define SQUASHFS_FILE_MAX_SIZE 65536 -+ -+/* Max number of uids and gids */ -+#define SQUASHFS_UIDS 256 -+#define SQUASHFS_GUIDS 255 -+ -+/* Max length of filename (not 255) */ -+#define SQUASHFS_NAME_LEN 256 -+ -+#define SQUASHFS_INVALID ((long long) 0xffffffffffff) -+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff) -+#define SQUASHFS_INVALID_BLK ((long long) -1) -+#define SQUASHFS_USED_BLK ((long long) -2) -+ -+/* Filesystem flags */ -+#define SQUASHFS_NOI 0 -+#define SQUASHFS_NOD 1 -+#define SQUASHFS_CHECK 2 -+#define SQUASHFS_NOF 3 -+#define SQUASHFS_NO_FRAG 4 -+#define SQUASHFS_ALWAYS_FRAG 5 -+#define SQUASHFS_DUPLICATE 6 -+ -+#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) -+ -+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOI) -+ -+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOD) -+ -+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NOF) -+ -+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_NO_FRAG) -+ -+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_ALWAYS_FRAG) -+ -+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_DUPLICATE) -+ -+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \ -+ SQUASHFS_CHECK) -+ -+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \ -+ duplicate_checking) (noi | (nod << 1) | (check_data << 2) \ -+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \ -+ (duplicate_checking << 6)) -+ -+/* Max number of types and file types */ -+#define SQUASHFS_DIR_TYPE 1 -+#define SQUASHFS_FILE_TYPE 2 -+#define SQUASHFS_SYMLINK_TYPE 3 -+#define SQUASHFS_BLKDEV_TYPE 4 -+#define SQUASHFS_CHRDEV_TYPE 5 -+#define SQUASHFS_FIFO_TYPE 6 -+#define SQUASHFS_SOCKET_TYPE 7 -+#define SQUASHFS_LDIR_TYPE 8 -+#define SQUASHFS_LREG_TYPE 9 -+ -+/* 1.0 filesystem type definitions */ -+#define SQUASHFS_TYPES 5 -+#define SQUASHFS_IPC_TYPE 0 -+ -+/* Flag whether block is compressed or uncompressed, bit is set if block is -+ * uncompressed */ -+#define SQUASHFS_COMPRESSED_BIT (1 << 15) -+ -+#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \ -+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT) -+ -+#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT)) -+ -+#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24) -+ -+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \ -+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \ -+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK) -+ -+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) -+ -+/* -+ * Inode number ops. Inodes consist of a compressed block number, and an -+ * uncompressed offset within that block -+ */ -+#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16)) -+ -+#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff)) -+ -+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\ -+ << 16) + (B))) -+ -+/* Compute 32 bit VFS inode number from squashfs inode number */ -+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \ -+ ((b) >> 2) + 1)) -+/* XXX */ -+ -+/* Translate between VFS mode and squashfs mode */ -+#define SQUASHFS_MODE(a) ((a) & 0xfff) -+ -+/* fragment and fragment table defines */ -+#define SQUASHFS_FRAGMENT_BYTES(A) (A * sizeof(struct squashfs_fragment_entry)) -+ -+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \ -+ SQUASHFS_METADATA_SIZE - 1) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\ -+ sizeof(long long)) -+ -+/* cached data constants for filesystem */ -+#define SQUASHFS_CACHED_BLKS 8 -+ -+#define SQUASHFS_MAX_FILE_SIZE_LOG 64 -+ -+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \ -+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2)) -+ -+#define SQUASHFS_MARKER_BYTE 0xff -+ -+/* meta index cache */ -+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int)) -+#define SQUASHFS_META_ENTRIES 31 -+#define SQUASHFS_META_NUMBER 8 -+#define SQUASHFS_SLOTS 4 -+ -+#include -+ -+struct meta_entry { -+ long long data_block; -+ unsigned int index_block; -+ unsigned short offset; -+ unsigned short pad; -+}; -+ -+struct meta_index { -+ unsigned int inode_number; -+ unsigned int offset; -+ unsigned short entries; -+ unsigned short skip; -+ unsigned short locked; -+ unsigned short pad; -+ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES]; -+}; -+ -+ -+/* -+ * definitions for structures on disk -+ */ -+ -+typedef long long squashfs_block_t; -+typedef long long squashfs_inode_t; -+ -+struct squashfs_super_block { -+ unsigned int s_magic; -+ unsigned int inodes; -+ unsigned int bytes_used_2; -+ unsigned int uid_start_2; -+ unsigned int guid_start_2; -+ unsigned int inode_table_start_2; -+ unsigned int directory_table_start_2; -+ unsigned int s_major:16; -+ unsigned int s_minor:16; -+ unsigned int block_size_1:16; -+ unsigned int block_log:16; -+ unsigned int flags:8; -+ unsigned int no_uids:8; -+ unsigned int no_guids:8; -+ unsigned int mkfs_time /* time of filesystem creation */; -+ squashfs_inode_t root_inode; -+ unsigned int block_size; -+ unsigned int fragments; -+ unsigned int fragment_table_start_2; -+ long long bytes_used; -+ long long uid_start; -+ long long guid_start; -+ long long inode_table_start; -+ long long directory_table_start; -+ long long fragment_table_start; -+ long long unused; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_index { -+ unsigned int index; -+ unsigned int start_block; -+ unsigned char size; -+ unsigned char name[0]; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_BASE_INODE_HEADER \ -+ unsigned int inode_type:4; \ -+ unsigned int mode:12; \ -+ unsigned int uid:8; \ -+ unsigned int guid:8; \ -+ unsigned int mtime; \ -+ unsigned int inode_number; -+ -+struct squashfs_base_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ squashfs_block_t start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ unsigned int file_size; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_lreg_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ squashfs_block_t start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ long long file_size; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int start_block; -+ unsigned int parent_inode; -+} __attribute__ ((packed)); -+ -+struct squashfs_ldir_inode_header { -+ SQUASHFS_BASE_INODE_HEADER; -+ unsigned int nlink; -+ unsigned int file_size:27; -+ unsigned int offset:13; -+ unsigned int start_block; -+ unsigned int i_count:16; -+ unsigned int parent_inode; -+ struct squashfs_dir_index index[0]; -+} __attribute__ ((packed)); -+ -+union squashfs_inode_header { -+ struct squashfs_base_inode_header base; -+ struct squashfs_dev_inode_header dev; -+ struct squashfs_symlink_inode_header symlink; -+ struct squashfs_reg_inode_header reg; -+ struct squashfs_lreg_inode_header lreg; -+ struct squashfs_dir_inode_header dir; -+ struct squashfs_ldir_inode_header ldir; -+ struct squashfs_ipc_inode_header ipc; -+}; -+ -+struct squashfs_dir_entry { -+ unsigned int offset:13; -+ unsigned int type:3; -+ unsigned int size:8; -+ int inode_number:16; -+ char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_header { -+ unsigned int count:8; -+ unsigned int start_block; -+ unsigned int inode_number; -+} __attribute__ ((packed)); -+ -+struct squashfs_fragment_entry { -+ long long start_block; -+ unsigned int size; -+ unsigned int unused; -+} __attribute__ ((packed)); -+ -+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen); -+extern int squashfs_uncompress_init(void); -+extern int squashfs_uncompress_exit(void); -+ -+/* -+ * macros to convert each packed bitfield structure from little endian to big -+ * endian and vice versa. These are needed when creating or using a filesystem -+ * on a machine with different byte ordering to the target architecture. -+ * -+ */ -+ -+#define SQUASHFS_SWAP_START \ -+ int bits;\ -+ int b_pos;\ -+ unsigned long long val;\ -+ unsigned char *s;\ -+ unsigned char *d; -+ -+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\ -+ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\ -+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\ -+ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\ -+ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\ -+ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\ -+ SQUASHFS_SWAP((s)->flags, d, 288, 8);\ -+ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\ -+ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\ -+ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\ -+ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\ -+ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\ -+ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\ -+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\ -+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\ -+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\ -+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\ -+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\ -+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\ -+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\ -+ SQUASHFS_SWAP((s)->unused, d, 888, 64);\ -+} -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ -+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32); -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_ipc_inode_header))\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_dev_inode_header)); \ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_reg_inode_header));\ -+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\ -+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_lreg_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\ -+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_dir_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\ -+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\ -+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \ -+ sizeof(struct squashfs_ldir_inode_header));\ -+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\ -+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\ -+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\ -+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\ -+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\ -+ SQUASHFS_SWAP((s)->index, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->size, d, 64, 8);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\ -+ SQUASHFS_SWAP((s)->count, d, 0, 8);\ -+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\ -+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ -+ SQUASHFS_SWAP((s)->type, d, 13, 3);\ -+ SQUASHFS_SWAP((s)->size, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\ -+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\ -+ SQUASHFS_SWAP((s)->size, d, 64, 32);\ -+} -+ -+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 2);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 16)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\ -+} -+ -+#define SQUASHFS_SWAP_INTS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 4);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 32)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\ -+} -+ -+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * 8);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ 64)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\ -+} -+ -+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\ -+ int entry;\ -+ int bit_position;\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, n * bits / 8);\ -+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \ -+ bits)\ -+ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n) -+ -+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY -+ -+struct squashfs_base_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int type:4; -+ unsigned int offset:4; -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int mtime; -+ unsigned int start_block; -+ unsigned int file_size:32; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header_1 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:4; /* index into uid table */ -+ unsigned int guid:4; /* index into guid table */ -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 4);\ -+ SQUASHFS_SWAP((s)->guid, d, 20, 4); -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_ipc_inode_header_1));\ -+ SQUASHFS_SWAP((s)->type, d, 24, 4);\ -+ SQUASHFS_SWAP((s)->offset, d, 28, 4);\ -+} -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_dev_inode_header_1));\ -+ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header_1));\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_reg_inode_header_1));\ -+ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \ -+ sizeof(struct squashfs_dir_inode_header_1));\ -+ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 43, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\ -+} -+ -+#endif -+ -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+ -+struct squashfs_dir_index_2 { -+ unsigned int index:27; -+ unsigned int start_block:29; -+ unsigned char size; -+ unsigned char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_base_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_ipc_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+} __attribute__ ((packed)); -+ -+struct squashfs_dev_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned short rdev; -+} __attribute__ ((packed)); -+ -+struct squashfs_symlink_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned short symlink_size; -+ char symlink[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_reg_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int mtime; -+ unsigned int start_block; -+ unsigned int fragment; -+ unsigned int offset; -+ unsigned int file_size:32; -+ unsigned short block_list[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int file_size:19; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+struct squashfs_ldir_inode_header_2 { -+ unsigned int inode_type:4; -+ unsigned int mode:12; /* protection */ -+ unsigned int uid:8; /* index into uid table */ -+ unsigned int guid:8; /* index into guid table */ -+ unsigned int file_size:27; -+ unsigned int offset:13; -+ unsigned int mtime; -+ unsigned int start_block:24; -+ unsigned int i_count:16; -+ struct squashfs_dir_index_2 index[0]; -+} __attribute__ ((packed)); -+ -+union squashfs_inode_header_2 { -+ struct squashfs_base_inode_header_2 base; -+ struct squashfs_dev_inode_header_2 dev; -+ struct squashfs_symlink_inode_header_2 symlink; -+ struct squashfs_reg_inode_header_2 reg; -+ struct squashfs_dir_inode_header_2 dir; -+ struct squashfs_ldir_inode_header_2 ldir; -+ struct squashfs_ipc_inode_header_2 ipc; -+}; -+ -+struct squashfs_dir_header_2 { -+ unsigned int count:8; -+ unsigned int start_block:24; -+} __attribute__ ((packed)); -+ -+struct squashfs_dir_entry_2 { -+ unsigned int offset:13; -+ unsigned int type:3; -+ unsigned int size:8; -+ char name[0]; -+} __attribute__ ((packed)); -+ -+struct squashfs_fragment_entry_2 { -+ unsigned int start_block; -+ unsigned int size; -+} __attribute__ ((packed)); -+ -+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ -+ SQUASHFS_MEMSET(s, d, n);\ -+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\ -+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\ -+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\ -+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\ -+ -+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\ -+} -+ -+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \ -+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2)) -+ -+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_dev_inode_header_2)); \ -+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\ -+} -+ -+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_symlink_inode_header_2));\ -+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\ -+} -+ -+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_reg_inode_header_2));\ -+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\ -+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\ -+ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_dir_inode_header_2));\ -+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\ -+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\ -+} -+ -+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \ -+ sizeof(struct squashfs_ldir_inode_header_2));\ -+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\ -+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\ -+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\ -+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\ -+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\ -+ SQUASHFS_SWAP((s)->index, d, 0, 27);\ -+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\ -+ SQUASHFS_SWAP((s)->size, d, 56, 8);\ -+} -+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\ -+ SQUASHFS_SWAP((s)->count, d, 0, 8);\ -+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\ -+} -+ -+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\ -+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\ -+ SQUASHFS_SWAP((s)->type, d, 13, 3);\ -+ SQUASHFS_SWAP((s)->size, d, 16, 8);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\ -+ SQUASHFS_SWAP_START\ -+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\ -+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\ -+ SQUASHFS_SWAP((s)->size, d, 32, 32);\ -+} -+ -+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n) -+ -+/* fragment and fragment table defines */ -+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2)) -+ -+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \ -+ SQUASHFS_METADATA_SIZE - 1) / \ -+ SQUASHFS_METADATA_SIZE) -+ -+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\ -+ sizeof(int)) -+ -+#endif -+ -+#ifdef __KERNEL__ -+ -+/* -+ * macros used to swap each structure entry, taking into account -+ * bitfields and different bitfield placing conventions on differing -+ * architectures -+ */ -+ -+#include -+ -+#ifdef __BIG_ENDIAN -+ /* convert from little endian to big endian */ -+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ -+ tbits, b_pos) -+#else -+ /* convert from big endian to little endian */ -+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \ -+ tbits, 64 - tbits - b_pos) -+#endif -+ -+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\ -+ b_pos = pos % 8;\ -+ val = 0;\ -+ s = (unsigned char *)p + (pos / 8);\ -+ d = ((unsigned char *) &val) + 7;\ -+ for(bits = 0; bits < (tbits + b_pos); bits += 8) \ -+ *d-- = *s++;\ -+ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\ -+} -+ -+#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n); -+ -+#endif -+#endif ---- /dev/null -+++ b/include/linux/squashfs_fs_i.h -@@ -0,0 +1,45 @@ -+#ifndef SQUASHFS_FS_I -+#define SQUASHFS_FS_I -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs_i.h -+ */ -+ -+struct squashfs_inode_info { -+ long long start_block; -+ unsigned int offset; -+ union { -+ struct { -+ long long fragment_start_block; -+ unsigned int fragment_size; -+ unsigned int fragment_offset; -+ long long block_list_start; -+ } s1; -+ struct { -+ long long directory_index_start; -+ unsigned int directory_index_offset; -+ unsigned int directory_index_count; -+ unsigned int parent_inode; -+ } s2; -+ } u; -+ struct inode vfs_inode; -+}; -+#endif ---- /dev/null -+++ b/include/linux/squashfs_fs_sb.h -@@ -0,0 +1,74 @@ -+#ifndef SQUASHFS_FS_SB -+#define SQUASHFS_FS_SB -+/* -+ * Squashfs -+ * -+ * Copyright (c) 2002, 2003, 2004, 2005, 2006 -+ * Phillip Lougher -+ * -+ * 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, -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * squashfs_fs_sb.h -+ */ -+ -+#include -+ -+struct squashfs_cache { -+ long long block; -+ int length; -+ long long next_index; -+ char *data; -+}; -+ -+struct squashfs_fragment_cache { -+ long long block; -+ int length; -+ unsigned int locked; -+ char *data; -+}; -+ -+struct squashfs_sb_info { -+ struct squashfs_super_block sblk; -+ int devblksize; -+ int devblksize_log2; -+ int swap; -+ struct squashfs_cache *block_cache; -+ struct squashfs_fragment_cache *fragment; -+ int next_cache; -+ int next_fragment; -+ int next_meta_index; -+ unsigned int *uid; -+ unsigned int *guid; -+ long long *fragment_index; -+ unsigned int *fragment_index_2; -+ unsigned int read_size; -+ char *read_data; -+ char *read_page; -+ struct semaphore read_data_mutex; -+ struct semaphore read_page_mutex; -+ struct semaphore block_cache_mutex; -+ struct semaphore fragment_mutex; -+ struct semaphore meta_index_mutex; -+ wait_queue_head_t waitq; -+ wait_queue_head_t fragment_wait_queue; -+ struct meta_index *meta_index; -+ struct inode *(*iget)(struct super_block *s, squashfs_inode_t \ -+ inode); -+ long long (*read_blocklist)(struct inode *inode, int \ -+ index, int readahead_blks, char *block_list, \ -+ unsigned short **block_p, unsigned int *bsize); -+ int (*read_fragment_index_table)(struct super_block *s); -+}; -+#endif ---- a/init/do_mounts_rd.c -+++ b/init/do_mounts_rd.c -@@ -5,6 +5,7 @@ - #include - #include - #include -+#include - #include - #include - -@@ -39,6 +40,7 @@ - * numbers could not be found. - * - * We currently check for the following magic numbers: -+ * squashfs - * minix - * ext2 - * romfs -@@ -53,6 +55,7 @@ - struct ext2_super_block *ext2sb; - struct romfs_super_block *romfsb; - struct cramfs_super *cramfsb; -+ struct squashfs_super_block *squashfsb; - int nblocks = -1; - unsigned char *buf; - -@@ -64,6 +67,7 @@ - ext2sb = (struct ext2_super_block *) buf; - romfsb = (struct romfs_super_block *) buf; - cramfsb = (struct cramfs_super *) buf; -+ squashfsb = (struct squashfs_super_block *) buf; - memset(buf, 0xe5, size); - - /* -@@ -101,6 +105,15 @@ - goto done; - } - -+ /* squashfs is at block zero too */ -+ if (squashfsb->s_magic == SQUASHFS_MAGIC) { -+ printk(KERN_NOTICE -+ "RAMDISK: squashfs filesystem found at block %d\n", -+ start_block); -+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS; -+ goto done; -+ } -+ - /* - * Read block 1 to test for minix and ext2 superblock - */ diff --git a/target/linux/generic-2.6/patches-2.6.22/002-lzma_decompress.patch b/target/linux/generic-2.6/patches-2.6.22/002-lzma_decompress.patch deleted file mode 100644 index f2f31f925..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/002-lzma_decompress.patch +++ /dev/null @@ -1,788 +0,0 @@ ---- /dev/null -+++ b/include/linux/LzmaDecode.h -@@ -0,0 +1,100 @@ -+/* -+ LzmaDecode.h -+ LZMA Decoder interface -+ -+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) -+ http://www.7-zip.org/ -+ -+ LZMA SDK is licensed under two licenses: -+ 1) GNU Lesser General Public License (GNU LGPL) -+ 2) Common Public License (CPL) -+ It means that you can select one of these two licenses and -+ follow rules of that license. -+ -+ SPECIAL EXCEPTION: -+ Igor Pavlov, as the author of this code, expressly permits you to -+ statically or dynamically link your code (or bind by name) to the -+ interfaces of this file without subjecting your linked code to the -+ terms of the CPL or GNU LGPL. Any modifications or additions -+ to this file, however, are subject to the LGPL or CPL terms. -+*/ -+ -+#ifndef __LZMADECODE_H -+#define __LZMADECODE_H -+ -+/* #define _LZMA_IN_CB */ -+/* Use callback for input data */ -+ -+/* #define _LZMA_OUT_READ */ -+/* Use read function for output data */ -+ -+/* #define _LZMA_PROB32 */ -+/* It can increase speed on some 32-bit CPUs, -+ but memory usage will be doubled in that case */ -+ -+/* #define _LZMA_LOC_OPT */ -+/* Enable local speed optimizations inside code */ -+ -+#ifndef UInt32 -+#ifdef _LZMA_UINT32_IS_ULONG -+#define UInt32 unsigned long -+#else -+#define UInt32 unsigned int -+#endif -+#endif -+ -+#ifdef _LZMA_PROB32 -+#define CProb UInt32 -+#else -+#define CProb unsigned short -+#endif -+ -+#define LZMA_RESULT_OK 0 -+#define LZMA_RESULT_DATA_ERROR 1 -+#define LZMA_RESULT_NOT_ENOUGH_MEM 2 -+ -+#ifdef _LZMA_IN_CB -+typedef struct _ILzmaInCallback -+{ -+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize); -+} ILzmaInCallback; -+#endif -+ -+#define LZMA_BASE_SIZE 1846 -+#define LZMA_LIT_SIZE 768 -+ -+/* -+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb) -+bufferSize += 100 in case of _LZMA_OUT_READ -+by default CProb is unsigned short, -+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int) -+*/ -+ -+#ifdef _LZMA_OUT_READ -+int LzmaDecoderInit( -+ unsigned char *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ unsigned char *dictionary, UInt32 dictionarySize, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ unsigned char *inStream, UInt32 inSize -+ #endif -+); -+#endif -+ -+int LzmaDecode( -+ unsigned char *buffer, -+ #ifndef _LZMA_OUT_READ -+ UInt32 bufferSize, -+ int lc, int lp, int pb, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback, -+ #else -+ unsigned char *inStream, UInt32 inSize, -+ #endif -+ #endif -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed); -+ -+#endif ---- /dev/null -+++ b/lib/LzmaDecode.c -@@ -0,0 +1,663 @@ -+/* -+ LzmaDecode.c -+ LZMA Decoder -+ -+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25) -+ http://www.7-zip.org/ -+ -+ LZMA SDK is licensed under two licenses: -+ 1) GNU Lesser General Public License (GNU LGPL) -+ 2) Common Public License (CPL) -+ It means that you can select one of these two licenses and -+ follow rules of that license. -+ -+ SPECIAL EXCEPTION: -+ Igor Pavlov, as the author of this code, expressly permits you to -+ statically or dynamically link your code (or bind by name) to the -+ interfaces of this file without subjecting your linked code to the -+ terms of the CPL or GNU LGPL. Any modifications or additions -+ to this file, however, are subject to the LGPL or CPL terms. -+*/ -+ -+#include -+ -+#ifndef Byte -+#define Byte unsigned char -+#endif -+ -+#define kNumTopBits 24 -+#define kTopValue ((UInt32)1 << kNumTopBits) -+ -+#define kNumBitModelTotalBits 11 -+#define kBitModelTotal (1 << kNumBitModelTotalBits) -+#define kNumMoveBits 5 -+ -+typedef struct _CRangeDecoder -+{ -+ Byte *Buffer; -+ Byte *BufferLim; -+ UInt32 Range; -+ UInt32 Code; -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *InCallback; -+ int Result; -+ #endif -+ int ExtraBytes; -+} CRangeDecoder; -+ -+Byte RangeDecoderReadByte(CRangeDecoder *rd) -+{ -+ if (rd->Buffer == rd->BufferLim) -+ { -+ #ifdef _LZMA_IN_CB -+ UInt32 size; -+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size); -+ rd->BufferLim = rd->Buffer + size; -+ if (size == 0) -+ #endif -+ { -+ rd->ExtraBytes = 1; -+ return 0xFF; -+ } -+ } -+ return (*rd->Buffer++); -+} -+ -+/* #define ReadByte (*rd->Buffer++) */ -+#define ReadByte (RangeDecoderReadByte(rd)) -+ -+void RangeDecoderInit(CRangeDecoder *rd, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ Byte *stream, UInt32 bufferSize -+ #endif -+ ) -+{ -+ int i; -+ #ifdef _LZMA_IN_CB -+ rd->InCallback = inCallback; -+ rd->Buffer = rd->BufferLim = 0; -+ #else -+ rd->Buffer = stream; -+ rd->BufferLim = stream + bufferSize; -+ #endif -+ rd->ExtraBytes = 0; -+ rd->Code = 0; -+ rd->Range = (0xFFFFFFFF); -+ for(i = 0; i < 5; i++) -+ rd->Code = (rd->Code << 8) | ReadByte; -+} -+ -+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; -+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code; -+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; } -+ -+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) -+{ -+ RC_INIT_VAR -+ UInt32 result = 0; -+ int i; -+ for (i = numTotalBits; i > 0; i--) -+ { -+ /* UInt32 t; */ -+ range >>= 1; -+ -+ result <<= 1; -+ if (code >= range) -+ { -+ code -= range; -+ result |= 1; -+ } -+ /* -+ t = (code - range) >> 31; -+ t &= 1; -+ code -= range & (t - 1); -+ result = (result + result) | (1 - t); -+ */ -+ RC_NORMALIZE -+ } -+ RC_FLUSH_VAR -+ return result; -+} -+ -+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) -+{ -+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob; -+ if (rd->Code < bound) -+ { -+ rd->Range = bound; -+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits; -+ if (rd->Range < kTopValue) -+ { -+ rd->Code = (rd->Code << 8) | ReadByte; -+ rd->Range <<= 8; -+ } -+ return 0; -+ } -+ else -+ { -+ rd->Range -= bound; -+ rd->Code -= bound; -+ *prob -= (*prob) >> kNumMoveBits; -+ if (rd->Range < kTopValue) -+ { -+ rd->Code = (rd->Code << 8) | ReadByte; -+ rd->Range <<= 8; -+ } -+ return 1; -+ } -+} -+ -+#define RC_GET_BIT2(prob, mi, A0, A1) \ -+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \ -+ if (code < bound) \ -+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \ -+ else \ -+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \ -+ RC_NORMALIZE -+ -+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) -+ -+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) -+{ -+ int mi = 1; -+ int i; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ for(i = numLevels; i > 0; i--) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + mi; -+ RC_GET_BIT(prob, mi) -+ #else -+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd); -+ #endif -+ } -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return mi - (1 << numLevels); -+} -+ -+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) -+{ -+ int mi = 1; -+ int i; -+ int symbol = 0; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ for(i = 0; i < numLevels; i++) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + mi; -+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i)) -+ #else -+ int bit = RangeDecoderBitDecode(probs + mi, rd); -+ mi = mi + mi + bit; -+ symbol |= (bit << i); -+ #endif -+ } -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) -+{ -+ int symbol = 1; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ do -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + symbol; -+ RC_GET_BIT(prob, symbol) -+ #else -+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); -+ #endif -+ } -+ while (symbol < 0x100); -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte) -+{ -+ int symbol = 1; -+ #ifdef _LZMA_LOC_OPT -+ RC_INIT_VAR -+ #endif -+ do -+ { -+ int bit; -+ int matchBit = (matchByte >> 7) & 1; -+ matchByte <<= 1; -+ #ifdef _LZMA_LOC_OPT -+ { -+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol; -+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1) -+ } -+ #else -+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd); -+ symbol = (symbol << 1) | bit; -+ #endif -+ if (matchBit != bit) -+ { -+ while (symbol < 0x100) -+ { -+ #ifdef _LZMA_LOC_OPT -+ CProb *prob = probs + symbol; -+ RC_GET_BIT(prob, symbol) -+ #else -+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd); -+ #endif -+ } -+ break; -+ } -+ } -+ while (symbol < 0x100); -+ #ifdef _LZMA_LOC_OPT -+ RC_FLUSH_VAR -+ #endif -+ return symbol; -+} -+ -+#define kNumPosBitsMax 4 -+#define kNumPosStatesMax (1 << kNumPosBitsMax) -+ -+#define kLenNumLowBits 3 -+#define kLenNumLowSymbols (1 << kLenNumLowBits) -+#define kLenNumMidBits 3 -+#define kLenNumMidSymbols (1 << kLenNumMidBits) -+#define kLenNumHighBits 8 -+#define kLenNumHighSymbols (1 << kLenNumHighBits) -+ -+#define LenChoice 0 -+#define LenChoice2 (LenChoice + 1) -+#define LenLow (LenChoice2 + 1) -+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) -+ -+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState) -+{ -+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0) -+ return RangeDecoderBitTreeDecode(p + LenLow + -+ (posState << kLenNumLowBits), kLenNumLowBits, rd); -+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0) -+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid + -+ (posState << kLenNumMidBits), kLenNumMidBits, rd); -+ return kLenNumLowSymbols + kLenNumMidSymbols + -+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd); -+} -+ -+#define kNumStates 12 -+ -+#define kStartPosModelIndex 4 -+#define kEndPosModelIndex 14 -+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) -+ -+#define kNumPosSlotBits 6 -+#define kNumLenToPosStates 4 -+ -+#define kNumAlignBits 4 -+#define kAlignTableSize (1 << kNumAlignBits) -+ -+#define kMatchMinLen 2 -+ -+#define IsMatch 0 -+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -+#define IsRepG0 (IsRep + kNumStates) -+#define IsRepG1 (IsRepG0 + kNumStates) -+#define IsRepG2 (IsRepG1 + kNumStates) -+#define IsRep0Long (IsRepG2 + kNumStates) -+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -+#define LenCoder (Align + kAlignTableSize) -+#define RepLenCoder (LenCoder + kNumLenProbs) -+#define Literal (RepLenCoder + kNumLenProbs) -+ -+#if Literal != LZMA_BASE_SIZE -+StopCompilingDueBUG -+#endif -+ -+#ifdef _LZMA_OUT_READ -+ -+typedef struct _LzmaVarState -+{ -+ CRangeDecoder RangeDecoder; -+ Byte *Dictionary; -+ UInt32 DictionarySize; -+ UInt32 DictionaryPos; -+ UInt32 GlobalPos; -+ UInt32 Reps[4]; -+ int lc; -+ int lp; -+ int pb; -+ int State; -+ int PreviousIsMatch; -+ int RemainLen; -+} LzmaVarState; -+ -+int LzmaDecoderInit( -+ unsigned char *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ unsigned char *dictionary, UInt32 dictionarySize, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback -+ #else -+ unsigned char *inStream, UInt32 inSize -+ #endif -+ ) -+{ -+ LzmaVarState *vs = (LzmaVarState *)buffer; -+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); -+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); -+ UInt32 i; -+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState)) -+ return LZMA_RESULT_NOT_ENOUGH_MEM; -+ vs->Dictionary = dictionary; -+ vs->DictionarySize = dictionarySize; -+ vs->DictionaryPos = 0; -+ vs->GlobalPos = 0; -+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1; -+ vs->lc = lc; -+ vs->lp = lp; -+ vs->pb = pb; -+ vs->State = 0; -+ vs->PreviousIsMatch = 0; -+ vs->RemainLen = 0; -+ dictionary[dictionarySize - 1] = 0; -+ for (i = 0; i < numProbs; i++) -+ p[i] = kBitModelTotal >> 1; -+ RangeDecoderInit(&vs->RangeDecoder, -+ #ifdef _LZMA_IN_CB -+ inCallback -+ #else -+ inStream, inSize -+ #endif -+ ); -+ return LZMA_RESULT_OK; -+} -+ -+int LzmaDecode(unsigned char *buffer, -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed) -+{ -+ LzmaVarState *vs = (LzmaVarState *)buffer; -+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); -+ CRangeDecoder rd = vs->RangeDecoder; -+ int state = vs->State; -+ int previousIsMatch = vs->PreviousIsMatch; -+ Byte previousByte; -+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; -+ UInt32 nowPos = 0; -+ UInt32 posStateMask = (1 << (vs->pb)) - 1; -+ UInt32 literalPosMask = (1 << (vs->lp)) - 1; -+ int lc = vs->lc; -+ int len = vs->RemainLen; -+ UInt32 globalPos = vs->GlobalPos; -+ -+ Byte *dictionary = vs->Dictionary; -+ UInt32 dictionarySize = vs->DictionarySize; -+ UInt32 dictionaryPos = vs->DictionaryPos; -+ -+ if (len == -1) -+ { -+ *outSizeProcessed = 0; -+ return LZMA_RESULT_OK; -+ } -+ -+ while(len > 0 && nowPos < outSize) -+ { -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ len--; -+ } -+ if (dictionaryPos == 0) -+ previousByte = dictionary[dictionarySize - 1]; -+ else -+ previousByte = dictionary[dictionaryPos - 1]; -+#else -+ -+int LzmaDecode( -+ Byte *buffer, UInt32 bufferSize, -+ int lc, int lp, int pb, -+ #ifdef _LZMA_IN_CB -+ ILzmaInCallback *inCallback, -+ #else -+ unsigned char *inStream, UInt32 inSize, -+ #endif -+ unsigned char *outStream, UInt32 outSize, -+ UInt32 *outSizeProcessed) -+{ -+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); -+ CProb *p = (CProb *)buffer; -+ CRangeDecoder rd; -+ UInt32 i; -+ int state = 0; -+ int previousIsMatch = 0; -+ Byte previousByte = 0; -+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; -+ UInt32 nowPos = 0; -+ UInt32 posStateMask = (1 << pb) - 1; -+ UInt32 literalPosMask = (1 << lp) - 1; -+ int len = 0; -+ if (bufferSize < numProbs * sizeof(CProb)) -+ return LZMA_RESULT_NOT_ENOUGH_MEM; -+ for (i = 0; i < numProbs; i++) -+ p[i] = kBitModelTotal >> 1; -+ RangeDecoderInit(&rd, -+ #ifdef _LZMA_IN_CB -+ inCallback -+ #else -+ inStream, inSize -+ #endif -+ ); -+#endif -+ -+ *outSizeProcessed = 0; -+ while(nowPos < outSize) -+ { -+ int posState = (int)( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ & posStateMask); -+ #ifdef _LZMA_IN_CB -+ if (rd.Result != LZMA_RESULT_OK) -+ return rd.Result; -+ #endif -+ if (rd.ExtraBytes != 0) -+ return LZMA_RESULT_DATA_ERROR; -+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0) -+ { -+ CProb *probs = p + Literal + (LZMA_LIT_SIZE * -+ ((( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ & literalPosMask) << lc) + (previousByte >> (8 - lc)))); -+ -+ if (state < 4) state = 0; -+ else if (state < 10) state -= 3; -+ else state -= 6; -+ if (previousIsMatch) -+ { -+ Byte matchByte; -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ matchByte = dictionary[pos]; -+ #else -+ matchByte = outStream[nowPos - rep0]; -+ #endif -+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); -+ previousIsMatch = 0; -+ } -+ else -+ previousByte = LzmaLiteralDecode(probs, &rd); -+ outStream[nowPos++] = previousByte; -+ #ifdef _LZMA_OUT_READ -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #endif -+ } -+ else -+ { -+ previousIsMatch = 1; -+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) -+ { -+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0) -+ { -+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0) -+ { -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos; -+ #endif -+ if ( -+ (nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ == 0) -+ return LZMA_RESULT_DATA_ERROR; -+ state = state < 7 ? 9 : 11; -+ #ifdef _LZMA_OUT_READ -+ pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ previousByte = dictionary[pos]; -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #else -+ previousByte = outStream[nowPos - rep0]; -+ #endif -+ outStream[nowPos++] = previousByte; -+ continue; -+ } -+ } -+ else -+ { -+ UInt32 distance; -+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) -+ distance = rep1; -+ else -+ { -+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) -+ distance = rep2; -+ else -+ { -+ distance = rep3; -+ rep3 = rep2; -+ } -+ rep2 = rep1; -+ } -+ rep1 = rep0; -+ rep0 = distance; -+ } -+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState); -+ state = state < 7 ? 8 : 11; -+ } -+ else -+ { -+ int posSlot; -+ rep3 = rep2; -+ rep2 = rep1; -+ rep1 = rep0; -+ state = state < 7 ? 7 : 10; -+ len = LzmaLenDecode(p + LenCoder, &rd, posState); -+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot + -+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << -+ kNumPosSlotBits), kNumPosSlotBits, &rd); -+ if (posSlot >= kStartPosModelIndex) -+ { -+ int numDirectBits = ((posSlot >> 1) - 1); -+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); -+ if (posSlot < kEndPosModelIndex) -+ { -+ rep0 += RangeDecoderReverseBitTreeDecode( -+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); -+ } -+ else -+ { -+ rep0 += RangeDecoderDecodeDirectBits(&rd, -+ numDirectBits - kNumAlignBits) << kNumAlignBits; -+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); -+ } -+ } -+ else -+ rep0 = posSlot; -+ rep0++; -+ } -+ if (rep0 == (UInt32)(0)) -+ { -+ /* it's for stream version */ -+ len = -1; -+ break; -+ } -+ if (rep0 > nowPos -+ #ifdef _LZMA_OUT_READ -+ + globalPos -+ #endif -+ ) -+ { -+ return LZMA_RESULT_DATA_ERROR; -+ } -+ len += kMatchMinLen; -+ do -+ { -+ #ifdef _LZMA_OUT_READ -+ UInt32 pos = dictionaryPos - rep0; -+ if (pos >= dictionarySize) -+ pos += dictionarySize; -+ previousByte = dictionary[pos]; -+ dictionary[dictionaryPos] = previousByte; -+ if (++dictionaryPos == dictionarySize) -+ dictionaryPos = 0; -+ #else -+ previousByte = outStream[nowPos - rep0]; -+ #endif -+ outStream[nowPos++] = previousByte; -+ len--; -+ } -+ while(len > 0 && nowPos < outSize); -+ } -+ } -+ -+ #ifdef _LZMA_OUT_READ -+ vs->RangeDecoder = rd; -+ vs->DictionaryPos = dictionaryPos; -+ vs->GlobalPos = globalPos + nowPos; -+ vs->Reps[0] = rep0; -+ vs->Reps[1] = rep1; -+ vs->Reps[2] = rep2; -+ vs->Reps[3] = rep3; -+ vs->State = state; -+ vs->PreviousIsMatch = previousIsMatch; -+ vs->RemainLen = len; -+ #endif -+ -+ *outSizeProcessed = nowPos; -+ return LZMA_RESULT_OK; -+} ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -13,7 +13,7 @@ - lib-y += kobject.o kref.o kobject_uevent.o klist.o - - obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ -- bust_spinlocks.o hexdump.o -+ bust_spinlocks.o hexdump.o LzmaDecode.o - - ifeq ($(CONFIG_DEBUG_KOBJECT),y) - CFLAGS_kobject.o += -DDEBUG -@@ -58,6 +58,7 @@ - obj-$(CONFIG_AUDIT_GENERIC) += audit.o - - obj-$(CONFIG_SWIOTLB) += swiotlb.o -+ - obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o - - lib-$(CONFIG_GENERIC_BUG) += bug.o diff --git a/target/linux/generic-2.6/patches-2.6.22/003-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.22/003-squashfs_lzma.patch deleted file mode 100644 index 16cc87319..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/003-squashfs_lzma.patch +++ /dev/null @@ -1,107 +0,0 @@ ---- a/fs/squashfs/inode.c -+++ b/fs/squashfs/inode.c -@@ -4,6 +4,9 @@ - * Copyright (c) 2002, 2003, 2004, 2005, 2006 - * Phillip Lougher - * -+ * LZMA decompressor support added by Oleg I. Vdovikin -+ * Copyright (c) 2005 Oleg I.Vdovikin -+ * - * 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, -@@ -21,6 +24,7 @@ - * inode.c - */ - -+#define SQUASHFS_LZMA - #include - #include - #include -@@ -44,6 +48,19 @@ - - #include "squashfs.h" - -+#ifdef SQUASHFS_LZMA -+#include -+ -+/* default LZMA settings, should be in sync with mksquashfs */ -+#define LZMA_LC 3 -+#define LZMA_LP 0 -+#define LZMA_PB 2 -+ -+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \ -+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb)) -+ -+#endif -+ - static void squashfs_put_super(struct super_block *); - static int squashfs_statfs(struct dentry *, struct kstatfs *); - static int squashfs_symlink_readpage(struct file *file, struct page *page); -@@ -64,7 +81,11 @@ - const char *, void *, struct vfsmount *); - - -+#ifdef SQUASHFS_LZMA -+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE]; -+#else - static z_stream stream; -+#endif - - static struct file_system_type squashfs_fs_type = { - .owner = THIS_MODULE, -@@ -249,6 +270,15 @@ - if (compressed) { - int zlib_err; - -+#ifdef SQUASHFS_LZMA -+ if ((zlib_err = LzmaDecode(lzma_workspace, -+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB, -+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK) -+ { -+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err); -+ bytes = 0; -+ } -+#else - stream.next_in = c_buffer; - stream.avail_in = c_byte; - stream.next_out = buffer; -@@ -263,7 +293,7 @@ - bytes = 0; - } else - bytes = stream.total_out; -- -+#endif - up(&msblk->read_data_mutex); - } - -@@ -2045,15 +2075,19 @@ - printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) " - "Phillip Lougher\n"); - -+#ifndef SQUASHFS_LZMA - if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) { - ERROR("Failed to allocate zlib workspace\n"); - destroy_inodecache(); - err = -ENOMEM; - goto out; - } -+#endif - - if ((err = register_filesystem(&squashfs_fs_type))) { -+#ifndef SQUASHFS_LZMA - vfree(stream.workspace); -+#endif - destroy_inodecache(); - } - -@@ -2064,7 +2098,9 @@ - - static void __exit exit_squashfs_fs(void) - { -+#ifndef SQUASHFS_LZMA - vfree(stream.workspace); -+#endif - unregister_filesystem(&squashfs_fs_type); - destroy_inodecache(); - } diff --git a/target/linux/generic-2.6/patches-2.6.22/004-extra_optimization.patch b/target/linux/generic-2.6/patches-2.6.22/004-extra_optimization.patch deleted file mode 100644 index 5e70e1b9b..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/004-extra_optimization.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/Makefile -+++ b/Makefile -@@ -507,6 +507,9 @@ - NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) - CHECKFLAGS += $(NOSTDINC_FLAGS) - -+# improve gcc optimization -+CFLAGS += $(call cc-option,-funit-at-a-time,) -+ - # warn about C99 declaration after statement - CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) - diff --git a/target/linux/generic-2.6/patches-2.6.22/006-gcc4_inline_fix.patch b/target/linux/generic-2.6/patches-2.6.22/006-gcc4_inline_fix.patch deleted file mode 100644 index 005908837..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/006-gcc4_inline_fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/include/asm-mips/system.h -+++ b/include/asm-mips/system.h -@@ -188,7 +188,7 @@ - if something tries to do an invalid xchg(). */ - extern void __xchg_called_with_bad_pointer(void); - --static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) - { - switch (size) { - case 4: diff --git a/target/linux/generic-2.6/patches-2.6.22/007-samsung_flash.patch b/target/linux/generic-2.6/patches-2.6.22/007-samsung_flash.patch deleted file mode 100644 index 335ffd9f9..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/007-samsung_flash.patch +++ /dev/null @@ -1,36 +0,0 @@ ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -51,6 +51,7 @@ - #define SST49LF040B 0x0050 - #define SST49LF008A 0x005a - #define AT49BV6416 0x00d6 -+#define MANUFACTURER_SAMSUNG 0x00ec - - static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); - static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -@@ -294,12 +295,19 @@ - - if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { -- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " -- "version %c.%c.\n", extp->MajorVersion, -- extp->MinorVersion); -- kfree(extp); -- kfree(mtd); -- return NULL; -+ if (cfi->mfr == MANUFACTURER_SAMSUNG && -+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) { -+ printk(KERN_NOTICE " Newer Samsung flash detected, " -+ "should be compatibile with Amd/Fujitsu.\n"); -+ } -+ else { -+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " -+ "version %c.%c.\n", extp->MajorVersion, -+ extp->MinorVersion); -+ kfree(extp); -+ kfree(mtd); -+ return NULL; -+ } - } - - /* Install our own private info structure */ diff --git a/target/linux/generic-2.6/patches-2.6.22/009-revert_intel_flash_breakage.patch b/target/linux/generic-2.6/patches-2.6.22/009-revert_intel_flash_breakage.patch deleted file mode 100644 index 51b84a745..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/009-revert_intel_flash_breakage.patch +++ /dev/null @@ -1,169 +0,0 @@ ---- a/drivers/mtd/chips/cfi_cmdset_0001.c -+++ b/drivers/mtd/chips/cfi_cmdset_0001.c -@@ -933,7 +933,7 @@ - - static int __xipram xip_wait_for_operation( - struct map_info *map, struct flchip *chip, -- unsigned long adr, unsigned int chip_op_time ) -+ unsigned long adr, int *chip_op_time ) - { - struct cfi_private *cfi = map->fldrv_priv; - struct cfi_pri_intelext *cfip = cfi->cmdset_priv; -@@ -942,7 +942,7 @@ - flstate_t oldstate, newstate; - - start = xip_currtime(); -- usec = chip_op_time * 8; -+ usec = *chip_op_time * 8; - if (usec == 0) - usec = 500000; - done = 0; -@@ -1052,8 +1052,8 @@ - #define XIP_INVAL_CACHED_RANGE(map, from, size) \ - INVALIDATE_CACHED_RANGE(map, from, size) - --#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ -- xip_wait_for_operation(map, chip, cmd_adr, usec) -+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ -+ xip_wait_for_operation(map, chip, cmd_adr, p_usec) - - #else - -@@ -1065,65 +1065,65 @@ - static int inval_cache_and_wait_for_operation( - struct map_info *map, struct flchip *chip, - unsigned long cmd_adr, unsigned long inval_adr, int inval_len, -- unsigned int chip_op_time) -+ int *chip_op_time ) - { - struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK = CMD(0x80); -- int chip_state = chip->state; -- unsigned int timeo, sleep_time; -+ int z, chip_state = chip->state; -+ unsigned long timeo; - - spin_unlock(chip->mutex); - if (inval_len) - INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); -+ if (*chip_op_time) -+ cfi_udelay(*chip_op_time); - spin_lock(chip->mutex); - -- /* set our timeout to 8 times the expected delay */ -- timeo = chip_op_time * 8; -- if (!timeo) -- timeo = 500000; -- sleep_time = chip_op_time / 2; -+ timeo = *chip_op_time * 8 * HZ / 1000000; -+ if (timeo < HZ/2) -+ timeo = HZ/2; -+ timeo += jiffies; - -+ z = 0; - for (;;) { -+ if (chip->state != chip_state) { -+ /* Someone's suspended the operation: sleep */ -+ DECLARE_WAITQUEUE(wait, current); -+ -+ set_current_state(TASK_UNINTERRUPTIBLE); -+ add_wait_queue(&chip->wq, &wait); -+ spin_unlock(chip->mutex); -+ schedule(); -+ remove_wait_queue(&chip->wq, &wait); -+ timeo = jiffies + (HZ / 2); /* FIXME */ -+ spin_lock(chip->mutex); -+ continue; -+ } -+ - status = map_read(map, cmd_adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - -- if (!timeo) { -+ /* OK Still waiting */ -+ if (time_after(jiffies, timeo)) { - map_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; - return -ETIME; - } - -- /* OK Still waiting. Drop the lock, wait a while and retry. */ -+ /* Latency issues. Drop the lock, wait a while and retry */ -+ z++; - spin_unlock(chip->mutex); -- if (sleep_time >= 1000000/HZ) { -- /* -- * Half of the normal delay still remaining -- * can be performed with a sleeping delay instead -- * of busy waiting. -- */ -- msleep(sleep_time/1000); -- timeo -= sleep_time; -- sleep_time = 1000000/HZ; -- } else { -- udelay(1); -- cond_resched(); -- timeo--; -- } -+ cfi_udelay(1); - spin_lock(chip->mutex); -- -- while (chip->state != chip_state) { -- /* Someone's suspended the operation: sleep */ -- DECLARE_WAITQUEUE(wait, current); -- set_current_state(TASK_UNINTERRUPTIBLE); -- add_wait_queue(&chip->wq, &wait); -- spin_unlock(chip->mutex); -- schedule(); -- remove_wait_queue(&chip->wq, &wait); -- spin_lock(chip->mutex); -- } - } - -+ if (!z) { -+ if (!--(*chip_op_time)) -+ *chip_op_time = 1; -+ } else if (z > 1) -+ ++(*chip_op_time); -+ - /* Done and happy. */ - chip->state = FL_STATUS; - return 0; -@@ -1132,7 +1132,8 @@ - #endif - - #define WAIT_TIMEOUT(map, chip, adr, udelay) \ -- INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); -+ ({ int __udelay = (udelay); \ -+ INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) - - - static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) -@@ -1356,7 +1357,7 @@ - - ret = INVAL_CACHE_AND_WAIT(map, chip, adr, - adr, map_bankwidth(map), -- chip->word_write_time); -+ &chip->word_write_time); - if (ret) { - xip_enable(map, chip, adr); - printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); -@@ -1593,7 +1594,7 @@ - - ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, - adr, len, -- chip->buffer_write_time); -+ &chip->buffer_write_time); - if (ret) { - map_write(map, CMD(0x70), cmd_adr); - chip->state = FL_STATUS; -@@ -1728,7 +1729,7 @@ - - ret = INVAL_CACHE_AND_WAIT(map, chip, adr, - adr, len, -- chip->erase_time); -+ &chip->erase_time); - if (ret) { - map_write(map, CMD(0x70), adr); - chip->state = FL_STATUS; diff --git a/target/linux/generic-2.6/patches-2.6.22/010-disable_old_squashfs_compatibility.patch b/target/linux/generic-2.6/patches-2.6.22/010-disable_old_squashfs_compatibility.patch deleted file mode 100644 index 01e27573b..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/010-disable_old_squashfs_compatibility.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/fs/squashfs/Makefile -+++ b/fs/squashfs/Makefile -@@ -4,4 +4,3 @@ - - obj-$(CONFIG_SQUASHFS) += squashfs.o - squashfs-y += inode.o --squashfs-y += squashfs2_0.o ---- a/fs/squashfs/squashfs.h -+++ b/fs/squashfs/squashfs.h -@@ -24,6 +24,9 @@ - #ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY - #undef CONFIG_SQUASHFS_1_0_COMPATIBILITY - #endif -+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY -+#endif - - #ifdef SQUASHFS_TRACE - #define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) diff --git a/target/linux/generic-2.6/patches-2.6.22/011-mips_boot.patch b/target/linux/generic-2.6/patches-2.6.22/011-mips_boot.patch deleted file mode 100644 index 6b1caca01..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/011-mips_boot.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/arch/mips/kernel/head.S -+++ b/arch/mips/kernel/head.S -@@ -129,11 +129,15 @@ - #endif - .endm - -+ -+ j kernel_entry -+ nop -+ - /* - * Reserved space for exception handlers. - * Necessary for machines which link their kernels at KSEG0. - */ -- .fill 0x400 -+ .align 10 - - EXPORT(stext) # used for profiling - EXPORT(_stext) diff --git a/target/linux/generic-2.6/patches-2.6.22/012-mips_cpu_tlb.patch b/target/linux/generic-2.6/patches-2.6.22/012-mips_cpu_tlb.patch deleted file mode 100644 index 47316d2d1..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/012-mips_cpu_tlb.patch +++ /dev/null @@ -1,18 +0,0 @@ ---- a/arch/mips/mm/tlbex.c -+++ b/arch/mips/mm/tlbex.c -@@ -887,7 +887,6 @@ - case CPU_R10000: - case CPU_R12000: - case CPU_R14000: -- case CPU_4KC: - case CPU_SB1: - case CPU_SB1A: - case CPU_4KSC: -@@ -915,6 +914,7 @@ - tlbw(p); - break; - -+ case CPU_4KC: - case CPU_4KEC: - case CPU_24K: - case CPU_34K: diff --git a/target/linux/generic-2.6/patches-2.6.22/013-mips_generic_gpio_support.patch b/target/linux/generic-2.6/patches-2.6.22/013-mips_generic_gpio_support.patch deleted file mode 100644 index 8f2632bef..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/013-mips_generic_gpio_support.patch +++ /dev/null @@ -1,32 +0,0 @@ ---- a/arch/mips/defconfig -+++ b/arch/mips/defconfig -@@ -69,6 +69,7 @@ - CONFIG_GENERIC_HWEIGHT=y - CONFIG_GENERIC_CALIBRATE_DELAY=y - CONFIG_GENERIC_TIME=y -+CONFIG_GENERIC_GPIO=n - CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y - # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set - CONFIG_ARC=y ---- a/arch/mips/Kconfig -+++ b/arch/mips/Kconfig -@@ -704,6 +704,10 @@ - bool - default y - -+config GENERIC_GPIO -+ bool -+ default n -+ - config SCHED_NO_NO_OMIT_FRAME_POINTER - bool - default y ---- /dev/null -+++ b/include/asm-mips/gpio.h -@@ -0,0 +1,6 @@ -+#ifndef _ASM_MIPS_GPIO_H -+#define _ASM_MIPS_GPIO_H -+ -+#include -+ -+#endif /* _ASM_MIPS_GPIO_H */ diff --git a/target/linux/generic-2.6/patches-2.6.22/014-x86_newsetup.patch b/target/linux/generic-2.6/patches-2.6.22/014-x86_newsetup.patch deleted file mode 100644 index 9d77c8396..000000000 --- a/target/linux/generic-2.6/patches-2.6.22/014-x86_newsetup.patch +++ /dev/null @@ -1,11865 +0,0 @@ -GIT 1783e2f0f21444020e3dee1be46b1e34af0ea3e7 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/hpa/linux-2.6-newsetup.git - -commit 1783e2f0f21444020e3dee1be46b1e34af0ea3e7 -Author: Venki Pallipadi -Date: Wed Jun 20 14:12:39 2007 -0700 - - Use a new CPU feature word to cover all Intel features that are spread around - - in different CPUID leafs like 0x5, 0x6 and 0xA. Make this - feature detection code common across i386 and x86_64. - - Display Intel Dynamic Acceleration feature in /proc/cpuinfo. This feature - will be enabled automatically by current acpi-cpufreq driver. - - Refer to Intel Software Developer's Manual for more details about the feature. - - Thanks to hpa (H Peter Anvin) for the making the actual code detecting the - scattered features data-driven. - - Signed-off-by: Venkatesh Pallipadi - Signed-off-by: H. Peter Anvin - -commit cd19eb67cd6636a4e5c9df99631422c7c7286f59 -Author: H. Peter Anvin -Date: Wed Jun 20 14:33:17 2007 -0700 - - x86 setup: move __bss_start into the .bss segment - - Move __bss_start into the .bss segment, and create __bss_end. - - Signed-off-by: H. Peter Anvin - -commit 100327ad6b609cd28970219be57d293847d1261d -Author: H. Peter Anvin -Date: Wed Jun 6 22:07:01 2007 -0700 - - x86 setup: remove TSC as a required feature - - Remove TSC as a required feature, in anticipation of CONFIG_X86_TSC - removal. - - Signed-off-by: H. Peter Anvin - -commit 7c91a172b8af7d4ba087f1f88ed5b155ed459ca3 -Author: Antonino A. Daplas -Date: Tue Jun 5 19:21:05 2007 +0800 - - i386: Set 6-bit DAC channel properties in vesa video setup - - If the video BIOS is not capable of switching or failed to switch the - hardware to 8-bit DAC, the channel properties are not set. This leads - to a blank (all black) display with vesafb at 8 bpp. Fix by defaulting - to a 6-bit DAC. - - Signed-off-by: Antonino Daplas - Signed-off-by: H. Peter Anvin - -commit 6eac2d442de8d87eac94a4ca8600bd87219fa06b -Author: H. Peter Anvin -Date: Tue Jun 5 16:19:36 2007 -0700 - - x86 setup: arch/i386/boot/cpucheck.c whitespace cleanup - - Remove stealth whitespace - - Signed-off-by: H. Peter Anvin - -commit f7d89f05a30433034a1b4651143afdbb2a8a9c92 -Author: H. Peter Anvin -Date: Thu May 24 16:56:44 2007 -0700 - - hd.c: remove BIOS/CMOS queries - - An ST-506 disk these days is pretty much someone trying to pull ancient - data using an auxilliary controller. Pulling data from the BIOS or CMOS - is just plain wrong, since it's likely to be the primary OS disk... and - would be user-entered data anyway. Instead, require the user enters it - on the command line. - - Signed-off-by: H. Peter Anvin - -commit 14c2fdb3bbfd6a9a774980e446c2443150749891 -Author: H. Peter Anvin -Date: Thu May 24 15:25:10 2007 -0700 - - x86: add back pbe bit to visible CPUID flags - - Add pbe back to the visible CPUID flags. We *do* correctly filter abuses - of this bit for 3DNow! in all the appropriate paths. - - Signed-off-by: H. Peter Anvin - -commit e071b068a3b9f318be314f0378e655e2eb50ac89 -Author: H. Peter Anvin -Date: Wed May 23 14:52:34 2007 -0700 - - x86 setup: VIA feature mask MSR doesn't just apply to model <= 9 - - The VIA feature mask MSR is known to be present on model 10, and it - seems likely it will continue to be supported. Since we only touch the - MSR if we're about to print an error message anyway, go ahead and be - aggressive. - - Signed-off-by: H. Peter Anvin - -commit abe0c5aa1827932cda9c754a3842ec22b278d704 -Author: H. Peter Anvin -Date: Tue May 22 17:17:41 2007 -0700 - - x86 setup: correct inline assembly constraints in edd.c - - Fix the inline assembly constraints in edd.c. In particular, "driveno" - was getting clobbered on some (buggy?) BIOSes. - - Signed-off-by: H. Peter Anvin - -commit c2e5887ad275aab90673a3e33344f09946159cf7 -Author: H. Peter Anvin -Date: Fri May 18 10:02:55 2007 -0700 - - x86 setup: force the assembler to generate a 2-byte jump in header - - The jump instruction in the header only has two bytes available, so - it *better* be a 2-byte jump! Unfortunately, the assembler will - always generate a 3/5-byte jump when the target is in a different - section. Deal with that by generating the jump instruction - explicitly from .byte's, just like we do elsewhere when we need a - specific binary representation of a certain instruction. - - Signed-off-by: H. Peter Anvin - -commit ce82e3b93eba48b6852822a03efa73c74e165d4f -Author: H. Peter Anvin -Date: Thu May 17 15:44:48 2007 -0700 - - x86 setup: move the symbol start_of_setup into the proper section. - - start_of_setup is the beginning of the executable code and should be - located in the appropriate section. - - Signed-off-by: H. Peter Anvin - -commit e5f3a529457a5bfaf8f8783fb86013221279a81c -Author: H. Peter Anvin -Date: Thu May 17 15:43:19 2007 -0700 - - x86 setup: add an ASSERT that the header ends up in the right place - - Just in case we have funnies involving the linker or people putting - inappropriate align statements, make the linker abort if the setup - header ends up in the wrong place. - - Signed-off-by: H. Peter Anvin - -commit d9dbde725687ab99d1f529f49f14d1e280cc5cac -Author: Alexander van Heukelum -Date: Thu May 17 20:54:25 2007 +0200 - - x86 new setup: use appropriate sections for code and data - - An intermediate elf file is generated for the 16-bit setup code. - The generated code can be viewed using objdump -m i8086 -d. As it - stands, it also tries to disassemble the bugger_off_msg, which - results in garbage. This introduces two new sections to separate - the code and the data part of the bootsector stub. It also moves - some code from the .header section (a data section) to .inittext. - - Signed-off-by: Alexander van Heukelum - -commit 0d7558a81cf61e9fd2332a54897c5fd18df0d7f2 -Author: H. Peter Anvin -Date: Wed May 16 22:03:16 2007 -0700 - - x86 setup: use -include code16gcc.h instead of explicit #include - - Use -include in the Makefile instead of #include to include code16gcc.h. - This really is more of a compiler switch than anything else, and is a lot - cleaner to do implicitly. - - Signed-off-by: H. Peter Anvin - -commit 017ce54e8a4a9628a76d6b510c7309a7e4e111a8 -Author: H. Peter Anvin -Date: Wed May 16 18:48:06 2007 -0700 - - x86 setup: enable features on Centaur (VIA) and Transmeta processors - - AMD are not the only ones who sometimes mask features which the kernel - may very well depend on. VIA and Transmeta do, too. Add code to enable - these features during checking. - - Signed-off-by: H. Peter Anvin - -commit b794f5f9c5089709f3df38c6d91869fa38a9c1a4 -Author: H. Peter Anvin -Date: Wed May 16 16:37:47 2007 -0700 - - x86 setup: in older versions of ld, ASSERT() is an expression - - Older versions of ld (pre-2.15 or so) need: - - . = ASSERT(foo, "msg"); - - instead of: - - ASSERT(foo, "msg") - - Signed-off-by: H. Peter Anvin - -commit 21c2b7c99c417d07015ee8e516a634ec3d98c4ee -Author: H. Peter Anvin -Date: Wed May 16 10:52:41 2007 -0700 - - x86 setup: print a warning message if the bootloader gave us no heap. - - If the bootloader is so old it doesn't set the CAN_USE_HEAP flag, - a lot of functionality will by necessity be disabled, so print a - warning message. This means either a 2.00 protocol bootloader or - a buggy bootloader; the Qemu bootloader falls in this category. - - Signed-off-by: H. Peter Anvin - -commit 52ca0431390d389a2a2246f02fe652ea84c1ddd8 -Author: H. Peter Anvin -Date: Wed May 16 10:51:03 2007 -0700 - - x86 setup: rely on a compiled-in default for load high/load low - - When deciding if we should move the kernel from 0x10000 to 0x1000, as - is required for a zImage kernel, rely on a compiled-in default since - Qemu unconditionally zeroes the loadflags. This, of course, is a bug - in Qemu, but still... - - Signed-off-by: H. Peter Anvin - -commit 4db77a97793104a32e5fb83e62b943fa144b329d -Author: H. Peter Anvin -Date: Wed May 16 08:45:37 2007 -0700 - - x86 setup: correct assembly constraints. - - Double use of "d" in an asm() constraints; most gcc versions correctly - detect and avoid using it, but some version of gcc runs itself into - a brick wall instead. Fix the one "d" which should have been "a". - - Signed-off-by: H. Peter Anvin - -commit 4fbccbc1457d6710d3a9ce55ad70ec6cb0b75fc5 -Author: H. Peter Anvin -Date: Tue May 15 09:16:29 2007 -0700 - - x86 setup: include not - - brings in the accessor functions, which may potentially - bring in all other kinds of kernel headers which are inappropriate for - the setup code. For the setup code, include - instead, which only includes the numeric constants. - - Signed-off-by: H. Peter Anvin - -commit 839cafa9c0020e7506722dd2a4fd82a71c2939cc -Author: H. Peter Anvin -Date: Mon May 14 15:49:01 2007 -0700 - - x86 setup: protocol 2.0[01]: base for CL_OFFSET depends on setup_move_size - - Handle the use of boot protocol 2.00 and 2.01: the base segment for - CL_OFFSET depends on the value of setup_move_size. - - Signed-off-by: H. Peter Anvin - -commit d60357ad68a694b03e9b952eadba5ac277c31df0 -Author: H. Peter Anvin -Date: Sat May 12 12:18:53 2007 -0700 - - x86 setup: remove unused variable - - Remove unused variable - - Signed-off-by: H. Peter Anvin - -commit e21a2030b01081612259847321bcce13eae1e883 -Author: Sam Ravnborg -Date: Sat May 12 12:17:30 2007 -0700 - - x86 setup: share i386 Makefile with x86_64 - - The boot Makefile for i386 and x86_64 are equal - except for the CFLAGS setting. - Teach x86_64 to use the Makefile from i386 and - make CFLAGS setting arch dependent in i386 Makefile. - - Signed-off-by: Sam Ravnborg - Signed-off-by: H. Peter Anvin - -commit 8618d92339d0d106045f98f34833d863c3235cdb -Author: H. Peter Anvin -Date: Sat May 12 00:32:12 2007 -0700 - - x86 setup: video-bios.c missed the pointer to the set_mode method! - - We need the actual pointer to the set_mode method (oops!) - - Signed-off-by: H. Peter Anvin - -commit 85dfc374ea9aad33b9e0315f07a4b2722dc11e3e -Author: H. Peter Anvin -Date: Sat May 12 00:14:43 2007 -0700 - - x86 setup: when setting unknown BIOS modes and failing, try to revert - - If we set an unknown BIOS mode and fail, then explicitly try to revert - to the original mode. - - Signed-off-by: H. Peter Anvin - -commit f4f7949f126d2f152b09fa9367b1ec693f2ea818 -Author: H. Peter Anvin -Date: Fri May 11 11:20:59 2007 -0700 - - x86 setup: fix typo "video_bios" should be "video-bios" - - Signed-off-by: H. Peter Anvin - -commit 51ba7113ea5b07189b7f8a0534d400a072535197 -Author: H. Peter Anvin -Date: Fri May 11 11:09:55 2007 -0700 - - x86 setup: allow setting VESA modes "blind" - - Apparently, people really do set VESA modes "blind". As a result, make - the framework for settting blind modes more general, to remove some - special cases. - - Signed-off-by: H. Peter Anvin - -commit 1b8f73d9b2bf7630a2914ddab606db16fddb509e -Author: H. Peter Anvin -Date: Thu May 10 22:08:45 2007 -0700 - - x86_64: CONFIG_PHYSICAL_ALIGN should be 2 MB - - It's not actually used yet, but set CONFIG_PHYSICAL_ALIGN to 2 MB - as it should be, to prevent conflicts with other works in progress. - - Signed-off-by: H. Peter Anvin - -commit b81f3c88923e4470cd0942d4596fafc0fb1cf4fd -Author: H. Peter Anvin -Date: Thu May 10 19:11:32 2007 -0700 - - x86 setup: remove debugging statements - - Remove debugging statements in video.c that were not meant for - production. - - Signed-off-by: H. Peter Anvin - -commit be58b6d7e9c14e482bce495e8343955999dea77f -Author: H. Peter Anvin -Date: Thu May 10 18:49:40 2007 -0700 - - x86 setup: only restore the screen image when needed - - Only restore the screen image when needed. This is how the original - code behaves, so it's presumably the desired behaviour. - - Signed-off-by: H. Peter Anvin - -commit 22f6bd8cc23b512af28e34ae7d40036982a0ac63 -Author: H. Peter Anvin -Date: Thu May 10 18:44:08 2007 -0700 - - x86 setup: correct the definition of the GDT limit - - Like all other x86 segment limits, the GDT limit points to the last byte - that is *permitted* to access, so it needs to be sizeof(boot_gdt)-1. - - Signed-off-by: H. Peter Anvin - -commit 7f73f1f4aa4c97745bffe07a3ebcf226a4965b00 -Author: H. Peter Anvin -Date: Thu May 10 15:47:48 2007 -0700 - - x86 setup: Re-implement scanning for hidden video modes - - Re-implement scanning for hidden video modes. Every now and then, - apparently, you can find them hidden like easter eggs. - - Signed-off-by: H. Peter Anvin - -commit 6770176714bc12ec92372311ac02c14f0d22776e -Author: H. Peter Anvin -Date: Thu May 10 15:24:27 2007 -0700 - - x86 setup: whitespace cleanup - - Clean up stealth whitespace. - - Signed-off-by: H. Peter Anvin - -commit ba0480a3537cf471b08bdb99dae6d0780cfb1972 -Author: H. Peter Anvin -Date: Wed May 9 16:54:42 2007 -0700 - - x86: sync the CPU feature string arrays - - With unified, synchronize the CPU feature string - arrays. The whole kernel/cpu directory really needs to be unified. - - Signed-off-by: H. Peter Anvin - -commit ecb53b84efddbad3d9aa49e95598550831324348 -Author: H. Peter Anvin -Date: Tue May 8 22:06:04 2007 -0700 - - x86 setup: need to set orig_video_isVGA - - After detecting a VGA console, we need to set - boot_params.screen_info.orig_video_isVGA. - - Signed-off-by: H. Peter Anvin - -commit dc97fc053faff17b984ec962686caea52bd27628 -Author: H. Peter Anvin -Date: Tue May 8 20:51:17 2007 -0700 - - x86 setup: boot sector should use ljmp, not jmpl - - We have an "jmpl" instruction in the boot sector, which was meant - to be an "ljmp" instruction. It worked anyway because gas interpreted - a two-argument "jmpl" as an "ljmpl" instruction, however, use plain - "ljmp" (i.e. "ljmpw".) - - Signed-off-by: H. Peter Anvin - -commit 7907f05e9692557c53c9ac13647db5e5343c7c76 -Author: H. Peter Anvin -Date: Tue May 8 20:27:10 2007 -0700 - - x86 setup: only make VESA graphics modes selectable if CONFIG_FB - - If we select a VESA graphics mode, we better have framebuffer support - or the user will have no console. Therefore, make these modes - non-selectable if CONFIG_FB is not set. - - Signed-off-by: H. Peter Anvin - -commit 8e509f9ebc44f45544d231454e84f10bf78d5772 -Author: H. Peter Anvin -Date: Tue May 8 20:24:11 2007 -0700 - - x86 setup: need to probe VESA EDID block 0 only - - The VESA EDID BIOS call takes the EDID block number in %dx, and may - corrupt it by spec. Pass it in properly. - - Signed-off-by: H. Peter Anvin - -commit 9912b9aed7943773d1fadaa2e2e52f42af395048 -Author: H. Peter Anvin -Date: Mon May 7 18:22:04 2007 -0700 - - x86 setup: add missing file "bitops.h" missing from previous checkins - - The file "bitops.h" was missing from previous checkins. - - Signed-off-by: H. Peter Anvin - -commit 732eb3fac2d772980e6555b8c69902c8107c72aa -Author: H. Peter Anvin -Date: Mon May 7 14:59:43 2007 -0700 - - x86 setup: add -fno-stack-protector; other Makefile fixes - - Add -fno-stack-protector for the gcc's that need that; - Use -ffreestanding consistently; - Use $(LINUXINCLUDE); - Handle linker scripts consistently with other Makefiles. - - Signed-off-by: H. Peter Anvin - -commit 2d5e47f21202e156fe97aba0a88d158d5c157a33 -Author: H. Peter Anvin -Date: Mon May 7 14:45:25 2007 -0700 - - x86 setup: swap cpu.c and cpucheck.c; rename functions - - Make cpucheck.c the reusable component; the generically-named cpu.c - gets to be the wrapper. Accordingly, rename functions to make it - less confusing. - - Signed-off-by: H. Peter Anvin - -commit bf2a428a4e7c1ee3ab9acb23cfafb45e818887a1 -Author: H. Peter Anvin -Date: Mon May 7 14:09:38 2007 -0700 - - x86 setup: remove code moved from cpucheck.c -> cpu.c - - Move all info about requirements into cpu.c. - - Signed-off-by: H. Peter Anvin - -commit 9ea8429fabe5df6aed6393ac3a00d0b64445ba6a -Author: H. Peter Anvin -Date: Mon May 7 09:42:51 2007 -0700 - - x86 setup: remove double nesting of a20_test() - - a20_test() was invoked as either a20_test() or a20_wait(), where the - latter was simply a loop around a loop. Make the count a parameter - instead; this is clearer and saves a couple of bytes. - - Signed-off-by: H. Peter Anvin - -commit 9edc55718f57195c664ee3175514d652f651cfd2 -Author: H. Peter Anvin -Date: Mon May 7 09:30:41 2007 -0700 - - x86 setup: compile with -fomit-frame-pointer - - Compiling with -fomit-frame-pointer reduces the size by about 2%. - - Signed-off-by: H. Peter Anvin - -commit e1003433f2d491bf17c79437cd75268da220dab5 -Author: H. Peter Anvin -Date: Mon May 7 09:30:04 2007 -0700 - - x86 setup: be more paranoid about the stack setup in header.S - - In particular, deal correctly with the stack pointer being zero on entry. - While we're at it, align the stack. - - Signed-off-by: H. Peter Anvin - -commit 853499c3dc3fcbeb192a613ac241d150ebc7c5a0 -Author: H. Peter Anvin -Date: Sun May 6 23:25:10 2007 -0700 - - x86 setup: Factor out the environment-independent part of the CPU check. - - Factor out the environment-independent part of the CPU check so it can - be invoked from other parts of the kernel as well. - - Signed-off-by: H. Peter Anvin - -commit f235a61f6d6dff57883efad351d746540bcb8caf -Author: H. Peter Anvin -Date: Sat May 5 22:16:54 2007 -0700 - - x86 setup: when watching the setup size, take the stack into account - - When watching the setup size, we have to take the stack into account. - In particular, the stack is used not only by the setup code itself, but - by BIOS interrupt handlers and system calls. Reserve a minimum of - 512 bytes. - - Signed-off-by: H. Peter Anvin - -commit 0d0e10091be48f7e4c8888e9d5c2836c704994f5 -Author: H. Peter Anvin -Date: Sat May 5 19:25:51 2007 -0700 - - x86 setup: actually check the end of the heap. - - Keep track of where the heap ends and actually watch out for it. - - Signed-off-by: H. Peter Anvin - -commit 47aab0b8f4d012fad3c42b5b0754d3cb87961b37 -Author: H. Peter Anvin -Date: Sat May 5 15:47:58 2007 -0700 - - x86 setup: coppyright rPath, Inc. - - This work was done on the dime of rPath, Inc.; they own the copyright. - - Signed-off-by: H. Peter Anvin - -commit d22571534d7eabf9408f29d9da423e1c6e04445f -Author: H. Peter Anvin -Date: Sat May 5 15:21:11 2007 -0700 - - x86 setup: implement screen contents save/restore - - The old setup code had screen contents save and restore, so implement - it for the new one as well. - - Signed-off-by: H. Peter Anvin - -commit e5145601a752bd998e783d159c187d3017d45d6d -Author: H. Peter Anvin -Date: Sat May 5 15:20:19 2007 -0700 - - x86 setup: whitespace cleanup - - Signed-off-by: H. Peter Anvin - -commit 045ecb52f91a74eecad93ffc8791eefe59cf7fd1 -Author: H. Peter Anvin -Date: Sat May 5 14:22:39 2007 -0700 - - x86 setup: allow setting of VESA graphics modes; cleanups - - - Allow setting of VESA graphics modes (used by vesafb) - - Clean up the macros related to the heap - - #if 0 copy functions that aren't actually currently being used - - Signed-off-by: H. Peter Anvin - -commit 58c04ed7e2d7d5979e1917a74b49bdc0f3dde211 -Author: H. Peter Anvin -Date: Sat May 5 12:06:14 2007 -0700 - - x86 setup: move all VESA-related code into video-vesa.c; add EDID - - - Move all VESA-related code into video-vesa.c - - Add VESA EDID query support - - Remove some totally obsolete definitions from video.h - - Signed-off-by: H. Peter Anvin - -commit 07bc3931175fb98256140275c03194426d441b74 -Author: H. Peter Anvin -Date: Sat May 5 12:04:40 2007 -0700 - - x86-64: remove -traditional from AFLAGS - - In arch/x86_64/boot/compressed, remove -traditional from AFLAGS. - - Signed-off-by: H. Peter Anvin - -commit a830f615eeef838d461cbf7bbbee8c1c84708ec8 -Author: H. Peter Anvin -Date: Fri May 4 18:44:38 2007 -0700 - - x86 setup: share code between i386 and x86-64 - - Share the boot (setup) code and tools between i386 and x86-64. - The compression code is now running in 64-bit mode in order to support - relocation, so do *not* share that code. - - Signed-off-by: H. Peter Anvin - -commit 3e159a323bdfa5d5a7be2c1f6be089ca22d598e0 -Author: H. Peter Anvin -Date: Fri May 4 18:43:35 2007 -0700 - - x86-64: use 0x1b4 as the scratch area in boot_params, not 0x3c - - Use 0x1b4 as the scratch area in boot_params rather than 0x3c. - - Signed-off-by: H. Peter Anvin - -commit 4cf4424e7a0f29f251b781f9b5e3655b0645cb7f -Author: H. Peter Anvin -Date: Fri May 4 18:26:18 2007 -0700 - - Revert "x86-64: Make arch/x86-64/boot a symlink to arch/i386/boot" - - This reverts commit b2ad90f4969226fe8cf3edc5330711ed5fc20105. - - Restore arch/x86_64/boot as a separate directory hierarchy. - - Conflicts: - -commit 8ed1ae1d2f94410811b7cca4b1a426e37652457f -Author: H. Peter Anvin -Date: Fri May 4 17:00:33 2007 -0700 - - x86-64: It appears MTRR isn't a required feature after all. - - MTRR was documented as a required feature, but appears to boot fine - without it (tested since Bochs doesn't have MTRR support.) - - Signed-off-by: H. Peter Anvin - -commit 7c616d098579fb790662cdc703f2a0f26ea1668c -Author: H. Peter Anvin -Date: Fri May 4 16:22:57 2007 -0700 - - x86 setup: use 0x1e4 as scratch, instead of 0x3c - - The compressed relocation needs a 4-byte scratch area to obtain - its own address. - - 0x3c is at the end of the video area, which is quite constrained -- it - only has 6 bytes left (12 if we recycle the obsolete fields which invade - this space.) Define 0x1e4 as a scratch field, and use it. - - Signed-off-by: H. Peter Anvin - -commit 5bc1019227e94576e4876d05ee920f59195bce90 -Author: H. Peter Anvin -Date: Fri May 4 16:09:15 2007 -0700 - - x86 setup: boot_params.e820_map is just the map, not the count; adjust - - boot_params.e820_map is just a list of entries, whereas - "struct e820map" contains a count as well. Thus, don't use - "struct e820map" to describe struct boot_params. - - Signed-off-by: H. Peter Anvin - -commit 0f96b52497f444be2d52d1184ca90be49f713ea3 -Author: H. Peter Anvin -Date: Fri May 4 15:49:03 2007 -0700 - - x86 setup: E820MAX is a definitional constant; no need to use sizeof hacks - - Now when we're using the standard headers for the setup code, we can use - E820MAX instead of playing sizeof games. - - Signed-off-by: H. Peter Anvin - -commit 3a23a428b20cbb31fd7ff5516a053b99afc447f7 -Author: H. Peter Anvin -Date: Fri May 4 12:08:46 2007 -0700 - - x86: move the bootparam structure definition into include/ - - Move the bootparam structure definition into include/, and make other - things use it. Haven't cleaned up all the macros yet, though. - - Signed-off-by: H. Peter Anvin - -commit e93ec58911995971aa059990f8a91a02b05f6c8f -Author: H. Peter Anvin -Date: Fri May 4 12:07:50 2007 -0700 - - i386: change %lu to %u in arch/i386/kernel/e820.h - - It's an u32, print it with %u - - Signed-off-by: H. Peter Anvin - -commit 2f47f004f614e2744867c0df274c55d8af2a42d5 -Author: H. Peter Anvin -Date: Fri May 4 12:06:04 2007 -0700 - - x86: fix differences between i386 and x86-64 - - Fix minor differences between i386 and x86-64 - - Signed-off-by: H. Peter Anvin - -commit 56ec52f14e948f430af941052adee98019a617b7 -Author: H. Peter Anvin -Date: Fri May 4 11:45:17 2007 -0700 - - x86: fix the definition of struct screen_info - - Name the fields that aren't really struct screen_info, and declare - the structure packed (the "capabilities" field is misaligned.) - - Signed-off-by: H. Peter Anvin - -commit 1d4429eaa564b0085d9ee3aa2de57e87a093a14e -Author: H. Peter Anvin -Date: Fri May 4 11:43:10 2007 -0700 - - x86-64: Make arch/x86-64/boot a symlink to arch/i386/boot - - Until such time that Kbuild allows for a cleaner solution, make - arch/x86-64/boot a symlink to arch/i386/boot. - - Signed-off-by: H. Peter Anvin - -commit 6a85f1b5fd041ea99d8604782559ce0502a60cc0 -Author: H. Peter Anvin -Date: Fri May 4 10:42:06 2007 -0700 - - x86-64: rearrange includes due to unifications and inclusion from setup - - Unification caused a circular dependency between - and ; resolve this. - - Add #ifndef _SETUP in so it can be included from the boot - code. - - Signed-off-by: H. Peter Anvin - -commit f6bbdc254bdbd5f7cf7a40c4cd6f9844af90824a -Author: H. Peter Anvin -Date: Fri May 4 10:40:26 2007 -0700 - - x86: Complete with the union of i386 and x86-64 - - Add a feature to which was previously present - in x86-64 but missing in i386. - - Signed-off-by: H. Peter Anvin - -commit 1a0819281060489901732914f67869e0aa8f26fd -Author: H. Peter Anvin -Date: Fri May 4 10:39:32 2007 -0700 - - x86: unify - - Unify between i386 and x86-64 - - Signed-off-by: H. Peter Anvin - -commit 8d9c54585f4623e0310f970fb5c6eda7ec1614df -Author: H. Peter Anvin -Date: Fri May 4 10:38:35 2007 -0700 - - x86-64: verify_cpu.S: use new masks - - Use the masks. - - Signed-off-by: H. Peter Anvin - -commit 6cf3308646bb7a3210f0f76bcb895b2dea76a93c -Author: H. Peter Anvin -Date: Fri May 4 10:37:26 2007 -0700 - - x86-64: fix compilation errors due to required-features.h change - - Fix compilation errors induced by required-features.h change. - - Signed-off-by: H. Peter Anvin - -commit 1324201a93ce380b46a3128826ecbd794e617e59 -Author: H. Peter Anvin -Date: Fri May 4 10:35:37 2007 -0700 - - x86-64: : add boot segment descriptors - - Add boot segment descriptors to to match i386. - - Signed-off-by: H. Peter Anvin - -commit a0b15a9e79ed0310813709cd0690d6838917fe82 -Author: H. Peter Anvin -Date: Fri May 4 10:34:37 2007 -0700 - - x86-64: add CONFIG_PHYSICAL_ALIGN to match i386 - - Add CONFIG_PHYSICAL_ALIGN to match i386, even though we don't use it. - - Signed-off-by: H. Peter Anvin - -commit 8f5d14d11a7318e257351ae477392c7f7e314602 -Author: H. Peter Anvin -Date: Fri May 4 10:33:54 2007 -0700 - - x86 setup: cleanups for compatibility with x86-64 - - These changes are necessary to compile on x86-64. - - Signed-off-by: H. Peter Anvin - -commit a32f68b6d4023c1c6b1e62e8561189516c571ab9 -Author: H. Peter Anvin -Date: Fri May 4 08:40:07 2007 -0700 - - x86 setup: add missing linker script - - Add linker script for the setup code, apparently missing from previous - checkins. - - Signed-off-by: H. Peter Anvin - -commit 4f34ca8e926b2d0bf3a7502b99f8dfced8cdba9d -Author: H. Peter Anvin -Date: Thu May 3 17:42:29 2007 -0700 - - x86 setup: paranoia: clear the high half of %esp - - We're invoked in 16-bit mode from an unknown bootloader. Make sure - we explicitly zero the upper half of %esp to avoid nasty surprises. - - Signed-off-by: H. Peter Anvin - -commit 19eb9b73cc1632a923003a002108b242af7a6080 -Author: H. Peter Anvin -Date: Thu May 3 17:35:41 2007 -0700 - - x86 setup: bootlin is *so* dead... - - Bootlin was never able to load bzImage kernels, so who cares about it. - - Signed-off-by: H. Peter Anvin - -commit 3b9fb73c65151ee043bc74c333d9e3c9b1872125 -Author: H. Peter Anvin -Date: Thu May 3 10:56:40 2007 -0700 - - x86 setup: apparently $(src) is insufficient, needs $(srctree)/$(src) - - For some unfanthomable reason the location of the source tree that - corresponds to the current directory has to be written as - $(srctree)/$(src) apparently. There might be a good reason for it, - but shorthand would be appreciated, and $(src) really should be the - short form. - - Signed-off-by: H. Peter Anvin - -commit a6d01d375a2269be1e3a6b31bcc4d426ad5a473d -Author: H. Peter Anvin -Date: Thu May 3 10:51:45 2007 -0700 - - x86 setup: remove reference to obsolete cpureq.c - - cpureq.c has been removed; remove it from the Makefile too. - - Signed-off-by: H. Peter Anvin - -commit cbe5b7585d800435080bcbf1b1fd242926982674 -Author: H. Peter Anvin -Date: Thu May 3 10:33:12 2007 -0700 - - x86 setup: use the required masks from - - Use the now-uniform features from . - - Signed-off-by: H. Peter Anvin - -commit 99ed30180ecc1bb4e93f6edda5f6bad1adf3e630 -Author: H. Peter Anvin -Date: Thu May 3 10:31:12 2007 -0700 - - x86: make the handling of required features consistent - - Make the handling of required features consistent between i386 - and x86-64. - - Signed-off-by: H. Peter Anvin - -commit 1120d70a2be8f2deb6bda64047da288d8f86dad3 -Author: H. Peter Anvin -Date: Thu May 3 00:09:53 2007 -0700 - - x86: Kconfig.cpu: the minimum CPU model is always 3; WP_WORKS_OK = i486 - - The minimum CPU model number is always 3 (i386), and if we have - WP_WORKS_OK it means we need an i486. - - Signed-off-by: H. Peter Anvin - -commit ebc308c204149b86984ae2216f5b9b2e63932028 -Author: H. Peter Anvin -Date: Thu May 3 00:08:48 2007 -0700 - - x86 setup: use CONFIG_X86_MINIMUM_CPU_MODEL - - Use CONFIG_X86_MINIMUM_CPU_MODEL as defined in Kconfig.cpu. - - Signed-off-by: H. Peter Anvin - -commit 8b50b640e015bf5d0f65502437da6fcab46c391b -Author: H. Peter Anvin -Date: Wed May 2 23:45:42 2007 -0700 - - x86 setup: remove bogus "static" - - Remove invalid "static" declarations in cpu.c - - Signed-off-by: H. Peter Anvin - -commit 35d23b60dfb110da81c24bcbfcda089cfc4fd264 -Author: H. Peter Anvin -Date: Wed May 2 23:37:50 2007 -0700 - - x86 setup: cpu detection cleanups - - - Use - - Make sure %cr0 isn't in a dangerous configuration before probing the FPU - - Signed-off-by: H. Peter Anvin - -commit a1150a03247b355d11a4bb696b8aae1f46612992 -Author: H. Peter Anvin -Date: Wed May 2 23:36:55 2007 -0700 - - x86 setup: compile with -DSETUP - - Define SETUP to make it easier to share code with the rest of the kernel. - - Signed-off-by: H. Peter Anvin - -commit 7eb52e8ad1bdf01886023d1a13b3313084cd7db6 -Author: H. Peter Anvin -Date: Wed May 2 23:34:57 2007 -0700 - - x86 setup: remove unused verify_cpu.S - - verify_cpu.S is obsoleted by boot/cpu.c. - - Signed-off-by: H. Peter Anvin - -commit e90317a027c30176968220d18eb18bd6a9d9cc74 -Author: H. Peter Anvin -Date: Wed May 2 20:07:43 2007 -0700 - - x86 setup: files missing from previous checkin (cpu.c, cpureq.c) - - These files were missing from a previous checkin; CPU feature-checking - code and the list of CPU features to check for. - - Signed-off-by: H. Peter Anvin - -commit 060f9b3db33c67b5344b2b4110bc823eb776e5cd -Author: H. Peter Anvin -Date: Wed May 2 19:51:34 2007 -0700 - - x86 setup: whitespace cleanup - - Signed-off-by: H. Peter Anvin - -commit 9f997a5569ec8fceaa15c2e9cf28e728e2ce118d -Author: H. Peter Anvin -Date: Wed May 2 19:07:14 2007 -0700 - - x86 setup: add CPU feature detect/abort on insufficient featurage - - The x86 setup is the right place to check features and abort if they - are not present, since we can still get a message to the user via the - firmware. - - Signed-off-by: H. Peter Anvin - -commit de4e976376fddec340651ef40b16a45f6189619d -Author: H. Peter Anvin -Date: Wed May 2 19:05:34 2007 -0700 - - x86 setup: whitespace cleanup - - Signed-off-by: H. Peter Anvin - -commit bcd2d2f8de5d4568b6628aa133fce1ac40ece526 -Author: H. Peter Anvin -Date: Wed May 2 16:19:59 2007 -0700 - - x86 setup: tag functions noreturn; error message on A20 failure - - Tag appropriate functions noreturn. - If the A20 gate fails, output an error message and refuse to boot. - - Signed-off-by: H. Peter Anvin - -commit 752aef90cbfc888084bf11fd83f8f72b6a668fc9 -Author: H. Peter Anvin -Date: Wed May 2 15:45:08 2007 -0700 - - x86 setup: clobber registers in keyboard BIOS call - - Keyboard BIOS call to set repeat rate is known to clobber registers on - "many" BIOSes. - - Signed-off-by: H. Peter Anvin - -commit dde94003e4759aab275732cf9f1834440cd381d0 -Author: H. Peter Anvin -Date: Wed May 2 15:44:21 2007 -0700 - - x86 setup: implement APM BIOS probe - - APM BIOS probe ported from assembly - - Signed-off-by: H. Peter Anvin - -commit 9403917d79e3349184318704476fa080836bd52c -Author: H. Peter Anvin -Date: Wed May 2 15:17:14 2007 -0700 - - x86 setup: remove references to obsolete probes - - Remove "Hello, World!" as well as references to probes which are no - longer used... - - Signed-off-by: H. Peter Anvin - -commit 712f65ffbd1d4b55b4c55d68b4dcd32406c28fb8 -Author: H. Peter Anvin -Date: Wed May 2 12:17:15 2007 -0700 - - x86 setup: video.c: correct the handling of special mode numbers - - Special mode numbers with the high bit set need to be handled *before* - masking out the high bit. - - Signed-off-by: H. Peter Anvin - -commit 9cf083204fe14cda3b09840eba8d131d2e48ccdf -Author: H. Peter Anvin -Date: Wed May 2 11:44:16 2007 -0700 - - x86 setup: Modern ATI cards pass the probe but lacks the modes. - - It appears modern ATI cards pass the probe for ATI-ness but lack the - modes. Kill off the driver as being incorrect. - - Signed-off-by: H. Peter Anvin - -commit 890cbe950589e30af17eac9da800efc76e35e01d -Author: H. Peter Anvin -Date: Wed May 2 11:32:21 2007 -0700 - - x86 setup: a20.c: make empty_8042() return status - - Make functions which could reasonably return status do so. It may - be relevant in the future, and it's a lot better if the programmer - doesn't have to figure out where everything should hook in. - - Just on principle. - - Signed-off-by: H. Peter Anvin - -commit 08a44dc655e0086d23fc3c70cb93eb51eaeec259 -Author: H. Peter Anvin -Date: Wed May 2 11:31:03 2007 -0700 - - x86 setup: video.c: clean up unused stuff - - Clean up unused variables that we have no intent on using, as well - as other cruft. - - Signed-off-by: H. Peter Anvin - -commit 57e69acff1f577de430cae1523fd49a5d113e885 -Author: H. Peter Anvin -Date: Wed May 2 11:18:13 2007 -0700 - - x86 setup: drop video mode range checking - - Drop video mode range checking. If someone really has, say, 12x40 mode - visible through the BIOS then allow them to select it... odds are low - that it will actually conflict with the very sparse allocation we have - anyway. - - Signed-off-by: H. Peter Anvin - -commit c0dda0b90f92d43872d55d295630a71cd357cfa6 -Author: H. Peter Anvin -Date: Wed May 2 11:15:53 2007 -0700 - - x86 setup: if no specific video mode ID is given, generate one - - If we don't specify a certain video mode ID in the driver, then - generate the 0xRRCC mode ID automatically. - - Signed-off-by: H. Peter Anvin - -commit 0db5086e79810e7c5d560006b1c9a7501a02d80c -Author: H. Peter Anvin -Date: Wed May 2 11:10:28 2007 -0700 - - x86 setup: Sadly, Cirrus removed extended text modes from their BIOS. - - In the later era of the Cirrus 54xx series, Cirrus removed extended text - modes from their BIOS. Neither Qemu nor Bochs implement them in the BIOS. - If we can find a direct-register-poking method of setting them that - works in Bochs/Qemu it might be worthwhile to resurrect this; the probing - routine *does* work. - - Of course, the Right Thing[TM] would be to submit such a routine to the - Bochs/Qemu BIOS as a VESA text mode. - - Signed-off-by: H. Peter Anvin - -commit 41f3fddeeb764687bf3fb0cf77fd858128571d58 -Author: H. Peter Anvin -Date: Wed May 2 10:18:07 2007 -0700 - - x86 setup: remove assembly implementation of putchar and puts - - Already unused, remove assembly implementation of putchar and puts. - - Signed-off-by: H. Peter Anvin - -commit dfa94cd86aca2c01d2f5e14b6e7c3e8258276195 -Author: H. Peter Anvin -Date: Tue May 1 21:41:28 2007 -0700 - - x86 setup: Call INT 15h AX=E820h properly - - The calling convention for BIOS call 15:E820 was messed up. - - Signed-off-by: H. Peter Anvin - -commit 2487575a36435c0a983febbb4f3751331bd2df7a -Author: H. Peter Anvin -Date: Tue May 1 21:34:12 2007 -0700 - - x86 setup: advance one e820 descriptor at a time... - - Adding sizeof(foo) to a foo * is not just useless, it's pretty damaging... - - Signed-off-by: H. Peter Anvin - -commit 530d4f4f1732335ae8725c0b8c332a618e63ea1d -Author: H. Peter Anvin -Date: Tue May 1 21:33:28 2007 -0700 - - x86 setup: fix memcmp_[fg]s() - - Actually return a value from memcmp_[fg]s()... - - Signed-off-by: H. Peter Anvin - -commit 8617cd56ff2e43303147da012b26c9dd46af726e -Author: H. Peter Anvin -Date: Tue May 1 21:32:47 2007 -0700 - - x86 setup: fix missing semicolon in video-ati.c - - Signed-off-by: H. Peter Anvin - -commit 7bbf7fa3e199b9cef4877c5a56128faff8636cc9 -Author: H. Peter Anvin -Date: Tue May 1 21:26:48 2007 -0700 - - x86 setup: make the video setup code actually do something... - - Basic video setup now works (there is still work to be done, however.) - - Signed-off-by: H. Peter Anvin - -commit 45bcd4406e4b812b32d317d9b3b8db2e5f135a3c -Author: H. Peter Anvin -Date: Tue May 1 21:25:20 2007 -0700 - - x86 setup: segment descriptors need to be Present - - The segment descriptors were missing the Present bit. - - Signed-off-by: H. Peter Anvin - -commit a39479d4ccf4dceffb623ad2ec7e2d708c38c637 -Author: H. Peter Anvin -Date: Tue May 1 21:24:32 2007 -0700 - - build: setup sectors doesn't include the boot sector - - The "setup sectors" field doesn't include the old boot sector, - even though the two are now one module. - - Signed-off-by: H. Peter Anvin - -commit d8f3d4928ead72e8febe2fcd740d0fee71a61f42 -Author: H. Peter Anvin -Date: Tue May 1 21:23:44 2007 -0700 - - x86 setup: in tty.c, actually tell it what character to print - - putchar() was missing the actual passing of the character code to the - BIOS call, with very silly-looking results. - - Signed-off-by: H. Peter Anvin - -commit 4f1462ed0377e180484a223e622d62432baa64b7 -Author: H. Peter Anvin -Date: Tue May 1 21:22:46 2007 -0700 - - x86 setup: printf.c needs code16gcc.h - - printf.c was missing code16gcc.h, with predictable consequences. - - Signed-off-by: H. Peter Anvin - -commit a5ba7e6df198bd204b0f87fc6e3f68388b9d14c1 -Author: H. Peter Anvin -Date: Mon Apr 30 20:56:42 2007 -0700 - - MAINTAINERS: formally take responsibility for the i386 boot code - - Change MAINTAINERS to formally take responsibility for the i386 boot code. - - Signed-off-by: H. Peter Anvin - -commit 6c821fc005655a99eff6e86c2e4b13654de94dea -Author: H. Peter Anvin -Date: Mon Apr 30 20:54:07 2007 -0700 - - x86 setup code rewrite: initial development snapshot - - Clean up the setup code and rewrite it in C. - This is an initial development snapshot, not a working tree. - - Signed-off-by: H. Peter Anvin -Signed-off-by: Andrew Morton ---- - - MAINTAINERS | 4 - arch/i386/Kconfig.cpu | 4 - arch/i386/boot/Makefile | 45 - arch/i386/boot/a20.c | 161 + - arch/i386/boot/apm.c | 97 - arch/i386/boot/bitops.h | 45 - arch/i386/boot/boot.h | 290 ++ - arch/i386/boot/bootsect.S | 98 - arch/i386/boot/cmdline.c | 97 - arch/i386/boot/code16gcc.h | 9 - arch/i386/boot/compressed/Makefile | 7 - arch/i386/boot/compressed/head.S | 6 - arch/i386/boot/compressed/misc.c | 3 - arch/i386/boot/copy.S | 101 - arch/i386/boot/cpu.c | 69 - arch/i386/boot/cpucheck.c | 266 ++ - arch/i386/boot/edd.S | 231 -- - arch/i386/boot/edd.c | 196 + - arch/i386/boot/header.S | 283 ++ - arch/i386/boot/main.c | 161 + - arch/i386/boot/mca.c | 43 - arch/i386/boot/memory.c | 99 - arch/i386/boot/pm.c | 170 + - arch/i386/boot/pmjump.S | 54 - arch/i386/boot/printf.c | 331 ++ - arch/i386/boot/setup.S | 1075 --------- - arch/i386/boot/setup.ld | 54 - arch/i386/boot/string.c | 34 - arch/i386/boot/tools/build.c | 156 - - arch/i386/boot/tty.c | 112 - arch/i386/boot/version.c | 23 - arch/i386/boot/vesa.h | 79 - arch/i386/boot/video-bios.c | 125 + - arch/i386/boot/video-vesa.c | 283 ++ - arch/i386/boot/video-vga.c | 260 ++ - arch/i386/boot/video.S | 2043 ------------------ - arch/i386/boot/video.c | 456 ++++ - arch/i386/boot/video.h | 145 + - arch/i386/boot/voyager.c | 46 - arch/i386/kernel/cpu/addon_cpuid_features.c | 50 - arch/i386/kernel/cpu/common.c | 2 - arch/i386/kernel/cpu/proc.c | 21 - arch/i386/kernel/e820.c | 2 - arch/i386/kernel/setup.c | 12 - arch/i386/kernel/verify_cpu.S | 94 - arch/x86_64/Kconfig | 4 - arch/x86_64/boot/Makefile | 136 - - arch/x86_64/boot/bootsect.S | 98 - arch/x86_64/boot/compressed/Makefile | 9 - arch/x86_64/boot/compressed/head.S | 6 - arch/x86_64/boot/install.sh | 2 - arch/x86_64/boot/mtools.conf.in | 17 - arch/x86_64/boot/setup.S | 826 ------- - arch/x86_64/boot/tools/build.c | 185 - - arch/x86_64/kernel/Makefile | 2 - arch/x86_64/kernel/setup.c | 21 - arch/x86_64/kernel/verify_cpu.S | 22 - drivers/ide/legacy/hd.c | 73 - include/asm-i386/boot.h | 6 - include/asm-i386/bootparam.h | 85 - include/asm-i386/cpufeature.h | 26 - include/asm-i386/e820.h | 14 - include/asm-i386/processor.h | 1 - include/asm-i386/required-features.h | 37 - include/asm-i386/setup.h | 10 - include/asm-x86_64/alternative.h | 68 - include/asm-x86_64/boot.h | 16 - include/asm-x86_64/bootparam.h | 1 - include/asm-x86_64/cpufeature.h | 115 - - include/asm-x86_64/e820.h | 6 - include/asm-x86_64/processor.h | 3 - include/asm-x86_64/required-features.h | 46 - include/asm-x86_64/segment.h | 8 - include/linux/edd.h | 4 - include/linux/screen_info.h | 9 - 75 files changed, 4594 insertions(+), 5204 deletions(-) - ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1750,8 +1750,8 @@ - S: Maintained - - i386 BOOT CODE --P: Riley H. Williams --M: Riley@Williams.Name -+P: H. Peter Anvin -+M: hpa@zytor.com - L: Linux-Kernel@vger.kernel.org - S: Maintained - ---- a/arch/i386/Kconfig.cpu -+++ b/arch/i386/Kconfig.cpu -@@ -346,6 +346,6 @@ - - config X86_MINIMUM_CPU_MODEL - int -- default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP -- default "0" -+ default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK -+ default "3" - ---- a/arch/i386/boot/Makefile -+++ b/arch/i386/boot/Makefile -@@ -25,27 +25,53 @@ - - #RAMDISK := -DRAMDISK=512 - --targets := vmlinux.bin bootsect bootsect.o \ -- setup setup.o zImage bzImage -+targets := vmlinux.bin setup.bin setup.elf zImage bzImage - subdir- := compressed - -+setup-y += a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o -+setup-y += header.o main.o mca.o memory.o pm.o pmjump.o -+setup-y += printf.o string.o tty.o video.o version.o voyager.o -+ -+# The link order of the video-*.o modules can matter. In particular, -+# video-vga.o *must* be listed first, followed by video-vesa.o. -+# Hardware-specific drivers should follow in the order they should be -+# probed, and video-bios.o should typically be last. -+setup-y += video-vga.o -+setup-y += video-vesa.o -+setup-y += video-bios.o -+ - hostprogs-y := tools/build - - HOSTCFLAGS_build.o := $(LINUXINCLUDE) - - # --------------------------------------------------------------------------- - -+# How to compile the 16-bit code. Note we always compile for -march=i386, -+# that way we can complain to the user if the CPU is insufficient. -+cflags-i386 := -+cflags-x86_64 := -m32 -+CFLAGS := $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \ -+ $(cflags-$(ARCH)) \ -+ -Wall -Wstrict-prototypes \ -+ -march=i386 -mregparm=3 \ -+ -include $(srctree)/$(src)/code16gcc.h \ -+ -fno-strict-aliasing -fomit-frame-pointer \ -+ $(call cc-option, -ffreestanding) \ -+ $(call cc-option, -fno-stack-protector) -+AFLAGS := $(CFLAGS) -D__ASSEMBLY__ -+ - $(obj)/zImage: IMAGE_OFFSET := 0x1000 - $(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) - $(obj)/bzImage: IMAGE_OFFSET := 0x100000 -+$(obj)/bzImage: EXTRA_CFLAGS := -D__BIG_KERNEL__ - $(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ - $(obj)/bzImage: BUILDFLAGS := -b - - quiet_cmd_image = BUILD $@ --cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ -+cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/setup.bin \ - $(obj)/vmlinux.bin $(ROOT_DEV) > $@ - --$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ -+$(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \ - $(obj)/vmlinux.bin $(obj)/tools/build FORCE - $(call if_changed,image) - @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' -@@ -53,12 +79,17 @@ - $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE - $(call if_changed,objcopy) - --LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary --LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext -+SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) - --$(obj)/setup $(obj)/bootsect: %: %.o FORCE -+LDFLAGS_setup.elf := -T -+$(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE - $(call if_changed,ld) - -+OBJCOPYFLAGS_setup.bin := -O binary -+ -+$(obj)/setup.bin: $(obj)/setup.elf FORCE -+ $(call if_changed,objcopy) -+ - $(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ - ---- /dev/null -+++ b/arch/i386/boot/a20.c -@@ -0,0 +1,161 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/a20.c -+ * -+ * Enable A20 gate (return -1 on failure) -+ */ -+ -+#include "boot.h" -+ -+#define MAX_8042_LOOPS 100000 -+ -+static int empty_8042(void) -+{ -+ u8 status; -+ int loops = MAX_8042_LOOPS; -+ -+ while (loops--) { -+ io_delay(); -+ -+ status = inb(0x64); -+ 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 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 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 a20_test_long(void) -+{ -+ return a20_test(A20_TEST_LONG); -+} -+ -+static void enable_a20_bios(void) -+{ -+ asm volatile("pushfl; int $0x15; popfl" -+ : : "a" ((u16)0x2401)); -+} -+ -+static void enable_a20_kbc(void) -+{ -+ empty_8042(); -+ -+ outb(0xd1, 0x64); /* Command write */ -+ empty_8042(); -+ -+ outb(0xdf, 0x60); /* A20 on */ -+ empty_8042(); -+} -+ -+static void 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 enable_a20(void) -+{ -+ int loops = A20_ENABLE_LOOPS; -+ -+#if defined(CONFIG_X86_ELAN) -+ /* Elan croaks if we try to touch the KBC */ -+ enable_a20_fast(); -+ while (!a20_test_long()) -+ ; -+ return 0; -+#elif defined(CONFIG_X86_VOYAGER) -+ /* On Voyager, a20_test() is unsafe? */ -+ enable_a20_kbc(); -+ return 0; -+#else -+ 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 */ -+ empty_8042(); -+ if (a20_test_short()) -+ return 0; /* BIOS worked, but with delayed reaction */ -+ -+ 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; -+#endif -+} ---- /dev/null -+++ b/arch/i386/boot/apm.c -@@ -0,0 +1,97 @@ -+/* -*- linux-c -*- ------------------------------------------------------- * -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ * Copyright 2007 rPath, Inc. - All Rights Reserved -+ * -+ * Original APM BIOS checking by Stephen Rothwell, May 1994 -+ * (sfr@canb.auug.org.au) -+ * -+ * This file is part of the Linux kernel, and is made available under -+ * the terms of the GNU General Public License version 2. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/apm.c -+ * -+ * Get APM BIOS information -+ */ -+ -+#include "boot.h" -+ -+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) -+ -+int query_apm_bios(void) -+{ -+ u16 ax, bx, cx, dx, di; -+ u32 ebx, esi; -+ u8 err; -+ -+ /* APM BIOS installation check */ -+ ax = 0x5300; -+ bx = cx = 0; -+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" -+ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) -+ : : "esi", "edi"); -+ -+ if (err) -+ return -1; /* No APM BIOS */ -+ -+ if (bx != 0x504d) /* "PM" signature */ -+ return -1; -+ -+ if (cx & 0x02) /* 32 bits supported? */ -+ return -1; -+ -+ /* Disconnect first, just in case */ -+ ax = 0x5304; -+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" -+ : "+a" (ax) -+ : : "ebx", "ecx", "edx", "esi", "edi"); -+ -+ /* Paranoia */ -+ ebx = esi = 0; -+ cx = dx = di = 0; -+ -+ /* 32-bit connect */ -+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %6" -+ : "=a" (ax), "+b" (ebx), "+c" (cx), "+d" (dx), -+ "+S" (esi), "+D" (di), "=m" (err) -+ : "a" (0x5303)); -+ -+ boot_params.apm_bios_info.cseg = ax; -+ boot_params.apm_bios_info.offset = ebx; -+ boot_params.apm_bios_info.cseg_16 = cx; -+ boot_params.apm_bios_info.dseg = dx; -+ boot_params.apm_bios_info.cseg_len = (u16)esi; -+ boot_params.apm_bios_info.cseg_16_len = esi >> 16; -+ boot_params.apm_bios_info.dseg_len = di; -+ -+ if (err) -+ return -1; -+ -+ /* Redo the installation check as the 32-bit connect; -+ some BIOSes return different flags this way... */ -+ -+ ax = 0x5300; -+ bx = cx = 0; -+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp ; setc %0" -+ : "=d" (err), "+a" (ax), "+b" (bx), "+c" (cx) -+ : : "esi", "edi"); -+ -+ if (err || bx != 0x504d) { -+ /* Failure with 32-bit connect, try to disconect and ignore */ -+ ax = 0x5304; -+ bx = 0; -+ asm volatile("pushl %%ebp ; int $0x15 ; popl %%ebp" -+ : "+a" (ax), "+b" (bx) -+ : : "ecx", "edx", "esi", "edi"); -+ return -1; -+ } -+ -+ boot_params.apm_bios_info.version = ax; -+ boot_params.apm_bios_info.flags = cx; -+ return 0; -+} -+ -+#endif ---- /dev/null -+++ b/arch/i386/boot/bitops.h -@@ -0,0 +1,45 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/bitops.h -+ * -+ * Very simple bitops for the boot code. -+ */ -+ -+#ifndef BOOT_BITOPS_H -+#define BOOT_BITOPS_H -+#define _LINUX_BITOPS_H /* Inhibit inclusion of */ -+ -+static inline int constant_test_bit(int nr, const void *addr) -+{ -+ const u32 *p = (const u32 *)addr; -+ return ((1UL << (nr & 31)) & (p[nr >> 5])) != 0; -+} -+static inline int variable_test_bit(int nr, const void *addr) -+{ -+ u8 v; -+ const u32 *p = (const u32 *)addr; -+ -+ asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); -+ return v; -+} -+ -+#define test_bit(nr,addr) \ -+(__builtin_constant_p(nr) ? \ -+ constant_test_bit((nr),(addr)) : \ -+ variable_test_bit((nr),(addr))) -+ -+static inline void set_bit(int nr, void *addr) -+{ -+ asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); -+} -+ -+#endif /* BOOT_BITOPS_H */ ---- /dev/null -+++ b/arch/i386/boot/boot.h -@@ -0,0 +1,290 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/boot.h -+ * -+ * Header file for the real-mode kernel code -+ */ -+ -+#ifndef BOOT_BOOT_H -+#define BOOT_BOOT_H -+ -+#ifndef __ASSEMBLY__ -+ -+#include -+#include -+#include -+#include -+#include -+ -+/* Useful macros */ -+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) -+ -+extern struct setup_header hdr; -+extern struct boot_params boot_params; -+ -+/* Basic port I/O */ -+static inline void outb(u8 v, u16 port) -+{ -+ asm volatile("outb %0,%1" : : "a" (v), "dN" (port)); -+} -+static inline u8 inb(u16 port) -+{ -+ u8 v; -+ asm volatile("inb %1,%0" : "=a" (v) : "dN" (port)); -+ return v; -+} -+ -+static inline void outw(u16 v, u16 port) -+{ -+ asm volatile("outw %0,%1" : : "a" (v), "dN" (port)); -+} -+static inline u16 inw(u16 port) -+{ -+ u16 v; -+ asm volatile("inw %1,%0" : "=a" (v) : "dN" (port)); -+ return v; -+} -+ -+static inline void outl(u32 v, u16 port) -+{ -+ asm volatile("outl %0,%1" : : "a" (v), "dn" (port)); -+} -+static inline u32 inl(u32 port) -+{ -+ u32 v; -+ asm volatile("inl %1,%0" : "=a" (v) : "dN" (port)); -+ return v; -+} -+ -+static inline void io_delay(void) -+{ -+ const u16 DELAY_PORT = 0x80; -+ asm volatile("outb %%al,%0" : : "dN" (DELAY_PORT)); -+} -+ -+/* These functions are used to reference data in other segments. */ -+ -+static inline u16 ds(void) -+{ -+ u16 seg; -+ asm("movw %%ds,%0" : "=rm" (seg)); -+ return seg; -+} -+ -+static inline void set_fs(u16 seg) -+{ -+ asm volatile("movw %0,%%fs" : : "rm" (seg)); -+} -+static inline u16 fs(void) -+{ -+ u16 seg; -+ asm("movw %%fs,%0" : "=rm" (seg)); -+ return seg; -+} -+ -+static inline void set_gs(u16 seg) -+{ -+ asm volatile("movw %0,%%gs" : : "rm" (seg)); -+} -+static inline u16 gs(void) -+{ -+ u16 seg; -+ asm("movw %%gs,%0" : "=rm" (seg)); -+ return seg; -+} -+ -+typedef unsigned int addr_t; -+ -+static inline u8 rdfs8(addr_t addr) -+{ -+ u8 v; -+ asm("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); -+ return v; -+} -+static inline u16 rdfs16(addr_t addr) -+{ -+ u16 v; -+ asm("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); -+ return v; -+} -+static inline u32 rdfs32(addr_t addr) -+{ -+ u32 v; -+ asm("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); -+ return v; -+} -+ -+static inline void wrfs8(u8 v, addr_t addr) -+{ -+ asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v)); -+} -+static inline void wrfs16(u16 v, addr_t addr) -+{ -+ asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v)); -+} -+static inline void wrfs32(u32 v, addr_t addr) -+{ -+ asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v)); -+} -+ -+static inline u8 rdgs8(addr_t addr) -+{ -+ u8 v; -+ asm("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr)); -+ return v; -+} -+static inline u16 rdgs16(addr_t addr) -+{ -+ u16 v; -+ asm("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr)); -+ return v; -+} -+static inline u32 rdgs32(addr_t addr) -+{ -+ u32 v; -+ asm("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr)); -+ return v; -+} -+ -+static inline void wrgs8(u8 v, addr_t addr) -+{ -+ asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v)); -+} -+static inline void wrgs16(u16 v, addr_t addr) -+{ -+ asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v)); -+} -+static inline void wrgs32(u32 v, addr_t addr) -+{ -+ asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v)); -+} -+ -+/* Note: these only return true/false, not a signed return value! */ -+static inline int memcmp(const void *s1, const void *s2, size_t len) -+{ -+ u8 diff; -+ asm("repe; cmpsb; setnz %0" -+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); -+ return diff; -+} -+ -+static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) -+{ -+ u8 diff; -+ asm("fs; repe; cmpsb; setnz %0" -+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); -+ return diff; -+} -+static inline int memcmp_gs(const void *s1, addr_t s2, size_t len) -+{ -+ u8 diff; -+ asm("gs; repe; cmpsb; setnz %0" -+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); -+ return diff; -+} -+ -+/* Heap -- available for dynamic lists. */ -+#define STACK_SIZE 512 /* Minimum number of bytes for stack */ -+ -+extern char _end[]; -+extern char *HEAP; -+extern char *heap_end; -+#define RESET_HEAP() ((void *)( HEAP = _end )) -+static inline char *__get_heap(size_t s, size_t a, size_t n) -+{ -+ char *tmp; -+ -+ HEAP = (char *)(((size_t)HEAP+(a-1)) & ~(a-1)); -+ tmp = HEAP; -+ HEAP += s*n; -+ return tmp; -+} -+#define GET_HEAP(type, n) \ -+ ((type *)__get_heap(sizeof(type),__alignof__(type),(n))) -+ -+static inline int heap_free(void) -+{ -+ return heap_end-HEAP; -+} -+ -+/* copy.S */ -+ -+void copy_to_fs(addr_t dst, void *src, size_t len); -+void *copy_from_fs(void *dst, addr_t src, size_t len); -+void copy_to_gs(addr_t dst, void *src, size_t len); -+void *copy_from_gs(void *dst, addr_t src, size_t len); -+void *memcpy(void *dst, void *src, size_t len); -+void *memset(void *dst, int c, size_t len); -+ -+#define memcpy(d,s,l) __builtin_memcpy(d,s,l) -+#define memset(d,c,l) __builtin_memset(d,c,l) -+ -+/* a20.c */ -+int enable_a20(void); -+ -+/* apm.c */ -+int query_apm_bios(void); -+ -+/* cmdline.c */ -+int cmdline_find_option(const char *option, char *buffer, int bufsize); -+ -+/* cpu.c, cpucheck.c */ -+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr); -+int validate_cpu(void); -+ -+/* edd.c */ -+void query_edd(void); -+ -+/* header.S */ -+void __attribute__((noreturn)) die(void); -+ -+/* mca.c */ -+int query_mca(void); -+ -+/* memory.c */ -+int detect_memory(void); -+ -+/* pm.c */ -+void __attribute__((noreturn)) go_to_protected_mode(void); -+ -+/* pmjump.S */ -+void __attribute__((noreturn)) -+ protected_mode_jump(u32 entrypoint, u32 bootparams); -+ -+/* printf.c */ -+unsigned int atou(const char *s); -+int sprintf(char *buf, const char *fmt, ...); -+int vsprintf(char *buf, const char *fmt, va_list args); -+int printf(const char *fmt, ...); -+ -+/* string.c */ -+int strcmp(const char *str1, const char *str2); -+ -+/* tty.c */ -+void puts(const char *); -+void putchar(int); -+int getchar(void); -+void kbd_flush(void); -+int getchar_timeout(void); -+ -+/* video.c */ -+void set_video(void); -+ -+/* video-vesa.c */ -+void vesa_store_edid(void); -+ -+/* voyager.c */ -+int query_voyager(void); -+ -+#endif /* __ASSEMBLY__ */ -+ -+#endif /* BOOT_BOOT_H */ ---- a/arch/i386/boot/bootsect.S -+++ /dev/null -@@ -1,98 +0,0 @@ --/* -- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds -- * -- * modified by Drew Eckhardt -- * modified by Bruce Evans (bde) -- * modified by Chris Noe (May 1999) (as86 -> gas) -- * gutted by H. Peter Anvin (Jan 2003) -- * -- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment -- * addresses must be multiplied by 16 to obtain their respective linear -- * addresses. To avoid confusion, linear addresses are written using leading -- * hex while segment addresses are written as segment:offset. -- * -- */ -- --#include -- --SETUPSECTS = 4 /* default nr of setup-sectors */ --BOOTSEG = 0x07C0 /* original address of boot-sector */ --INITSEG = DEF_INITSEG /* we move boot here - out of the way */ --SETUPSEG = DEF_SETUPSEG /* setup starts here */ --SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ --SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ -- /* to be loaded */ --ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ --SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ -- --#ifndef SVGA_MODE --#define SVGA_MODE ASK_VGA --#endif -- --#ifndef RAMDISK --#define RAMDISK 0 --#endif -- --#ifndef ROOT_RDONLY --#define ROOT_RDONLY 1 --#endif -- --.code16 --.text -- --.global _start --_start: -- -- # Normalize the start address -- jmpl $BOOTSEG, $start2 -- --start2: -- movw %cs, %ax -- movw %ax, %ds -- movw %ax, %es -- movw %ax, %ss -- movw $0x7c00, %sp -- sti -- cld -- -- movw $bugger_off_msg, %si -- --msg_loop: -- lodsb -- andb %al, %al -- jz die -- movb $0xe, %ah -- movw $7, %bx -- int $0x10 -- jmp msg_loop -- --die: -- # Allow the user to press a key, then reboot -- xorw %ax, %ax -- int $0x16 -- int $0x19 -- -- # int 0x19 should never return. In case it does anyway, -- # invoke the BIOS reset code... -- ljmp $0xf000,$0xfff0 -- -- --bugger_off_msg: -- .ascii "Direct booting from floppy is no longer supported.\r\n" -- .ascii "Please use a boot loader program instead.\r\n" -- .ascii "\n" -- .ascii "Remove disk and press any key to reboot . . .\r\n" -- .byte 0 -- -- -- # Kernel attributes; used by setup -- -- .org 497 --setup_sects: .byte SETUPSECTS --root_flags: .word ROOT_RDONLY --syssize: .word SYSSIZE --swap_dev: .word SWAP_DEV --ram_size: .word RAMDISK --vid_mode: .word SVGA_MODE --root_dev: .word ROOT_DEV --boot_flag: .word 0xAA55 ---- /dev/null -+++ b/arch/i386/boot/cmdline.c -@@ -0,0 +1,97 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/cmdline.c -+ * -+ * Simple command-line parser for early boot. -+ */ -+ -+#include "boot.h" -+ -+static inline int myisspace(u8 c) -+{ -+ return c <= ' '; /* Close enough approximation */ -+} -+ -+/* -+ * Find a non-boolean option, that is, "option=argument". In accordance -+ * with standard Linux practice, if this option is repeated, this returns -+ * the last instance on the command line. -+ * -+ * Returns the length of the argument (regardless of if it was -+ * truncated to fit in the buffer), or -1 on not found. -+ */ -+int cmdline_find_option(const char *option, char *buffer, int bufsize) -+{ -+ u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr; -+ addr_t cptr; -+ char c; -+ int len = -1; -+ const char *opptr = NULL; -+ char *bufptr = buffer; -+ enum { -+ st_wordstart, /* Start of word/after whitespace */ -+ st_wordcmp, /* Comparing this word */ -+ st_wordskip, /* Miscompare, skip */ -+ st_bufcpy /* Copying this to buffer */ -+ } state = st_wordstart; -+ -+ if (!cmdline_ptr || cmdline_ptr >= 0x100000) -+ return -1; /* No command line, or inaccessible */ -+ -+ cptr = cmdline_ptr & 0xf; -+ set_fs(cmdline_ptr >> 4); -+ -+ while (cptr < 0x10000 && (c = rdfs8(cptr++))) { -+ switch (state) { -+ case st_wordstart: -+ if (myisspace(c)) -+ break; -+ -+ /* else */ -+ state = st_wordcmp; -+ opptr = option; -+ /* fall through */ -+ -+ case st_wordcmp: -+ if (c == '=' && !*opptr) { -+ len = 0; -+ bufptr = buffer; -+ state = st_bufcpy; -+ } else if (myisspace(c)) { -+ state = st_wordstart; -+ } else if (c != *opptr++) { -+ state = st_wordskip; -+ } -+ break; -+ -+ case st_wordskip: -+ if (myisspace(c)) -+ state = st_wordstart; -+ break; -+ -+ case st_bufcpy: -+ if (myisspace(c)) { -+ state = st_wordstart; -+ } else { -+ if (len < bufsize-1) -+ *bufptr++ = c; -+ len++; -+ } -+ break; -+ } -+ } -+ -+ if (bufsize) -+ *bufptr = '\0'; -+ -+ return len; -+} ---- /dev/null -+++ b/arch/i386/boot/code16gcc.h -@@ -0,0 +1,9 @@ -+/* -+ * code16gcc.h -+ * -+ * This file is -include'd when compiling 16-bit C code. -+ */ -+ -+#ifndef __ASSEMBLY__ -+asm(".code16gcc"); -+#endif ---- a/arch/i386/boot/compressed/Makefile -+++ b/arch/i386/boot/compressed/Makefile -@@ -9,9 +9,14 @@ - EXTRA_AFLAGS := -traditional - - LDFLAGS_vmlinux := -T --CFLAGS_misc.o += -fPIC - hostprogs-y := relocs - -+CFLAGS := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ -+ -fno-strict-aliasing -fPIC \ -+ $(call cc-option,-ffreestanding) \ -+ $(call cc-option,-fno-stack-protector) -+LDFLAGS := -m elf_i386 -+ - $(obj)/vmlinux: $(src)/vmlinux.lds $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE - $(call if_changed,ld) - @: ---- a/arch/i386/boot/compressed/head.S -+++ b/arch/i386/boot/compressed/head.S -@@ -45,10 +45,10 @@ - * at and where we were actually loaded at. This can only be done - * with a short local call on x86. Nothing else will tell us what - * address we are running at. The reserved chunk of the real-mode -- * data at 0x34-0x3f are used as the stack for this calculation. -- * Only 4 bytes are needed. -+ * data at 0x1e4 (defined as a scratch field) are used as the stack -+ * for this calculation. Only 4 bytes are needed. - */ -- leal 0x40(%esi), %esp -+ leal (0x1e4+4)(%esi), %esp - call 1f - 1: popl %ebp - subl $1b, %ebp ---- a/arch/i386/boot/compressed/misc.c -+++ b/arch/i386/boot/compressed/misc.c -@@ -11,7 +11,6 @@ - - #undef CONFIG_PARAVIRT - #include --#include - #include - #include - #include -@@ -364,8 +363,10 @@ - - if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1)) - error("Destination address not CONFIG_PHYSICAL_ALIGN aligned"); -+#ifndef CONFIG_X86_64 - if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff)) - error("Destination address too large"); -+#endif - #ifndef CONFIG_RELOCATABLE - if ((u32)output != LOAD_PHYSICAL_ADDR) - error("Wrong destination address"); ---- /dev/null -+++ b/arch/i386/boot/copy.S -@@ -0,0 +1,101 @@ -+/* ----------------------------------------------------------------------- * -+ * -+ * 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/copy.S -+ * -+ * Memory copy routines -+ */ -+ -+ .code16gcc -+ .text -+ -+ .globl memcpy -+ .type memcpy, @function -+memcpy: -+ pushw %si -+ pushw %di -+ movw %ax, %di -+ movw %dx, %si -+ pushw %cx -+ shrw $2, %cx -+ rep; movsl -+ popw %cx -+ andw $3, %cx -+ rep; movsb -+ popw %di -+ popw %si -+ ret -+ .size memcpy, .-memcpy -+ -+ .globl memset -+ .type memset, @function -+memset: -+ pushw %di -+ movw %ax, %di -+ movzbl %dl, %eax -+ imull $0x01010101,%eax -+ pushw %cx -+ shrw $2, %cx -+ rep; stosl -+ popw %cx -+ andw $3, %cx -+ rep; stosb -+ popw %di -+ ret -+ .size memset, .-memset -+ -+ .globl copy_from_fs -+ .type copy_from_fs, @function -+copy_from_fs: -+ pushw %ds -+ pushw %fs -+ popw %ds -+ call memcpy -+ popw %ds -+ ret -+ .size copy_from_fs, .-copy_from_fs -+ -+ .globl copy_to_fs -+ .type copy_to_fs, @function -+copy_to_fs: -+ pushw %es -+ pushw %fs -+ popw %es -+ call memcpy -+ popw %es -+ ret -+ .size copy_to_fs, .-copy_to_fs -+ -+#if 0 /* Not currently used, but can be enabled as needed */ -+ -+ .globl copy_from_gs -+ .type copy_from_gs, @function -+copy_from_gs: -+ pushw %ds -+ pushw %gs -+ popw %ds -+ call memcpy -+ popw %ds -+ ret -+ .size copy_from_gs, .-copy_from_gs -+ .globl copy_to_gs -+ -+ .type copy_to_gs, @function -+copy_to_gs: -+ pushw %es -+ pushw %gs -+ popw %es -+ call memcpy -+ popw %es -+ ret -+ .size copy_to_gs, .-copy_to_gs -+ -+#endif ---- /dev/null -+++ b/arch/i386/boot/cpu.c -@@ -0,0 +1,69 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/cpucheck.c -+ * -+ * Check for obligatory CPU features and abort if the features are not -+ * present. -+ */ -+ -+#include "boot.h" -+#include "bitops.h" -+#include -+ -+static char *cpu_name(int level) -+{ -+ static char buf[6]; -+ -+ if (level == 64) { -+ return "x86-64"; -+ } else { -+ sprintf(buf, "i%d86", level); -+ return buf; -+ } -+} -+ -+int validate_cpu(void) -+{ -+ u32 *err_flags; -+ int cpu_level, req_level; -+ -+ check_cpu(&cpu_level, &req_level, &err_flags); -+ -+ if (cpu_level < req_level) { -+ printf("This kernel requires an %s CPU, ", -+ cpu_name(req_level)); -+ printf("but only detected an %s CPU.\n", -+ cpu_name(cpu_level)); -+ return -1; -+ } -+ -+ if (err_flags) { -+ int i, j; -+ puts("This kernel requires the following features " -+ "not present on the CPU:\n"); -+ -+ for (i = 0; i < NCAPINTS; i++) { -+ u32 e = err_flags[i]; -+ -+ for (j = 0; j < 32; j++) { -+ if (e & 1) -+ printf("%d:%d ", i, j); -+ -+ e >>= 1; -+ } -+ } -+ putchar('\n'); -+ return -1; -+ } else { -+ return 0; -+ } -+} ---- /dev/null -+++ b/arch/i386/boot/cpucheck.c -@@ -0,0 +1,266 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/cpu.c -+ * -+ * Check for obligatory CPU features and abort if the features are not -+ * present. This code should be compilable as 16-, 32- or 64-bit -+ * code, so be very careful with types and inline assembly. -+ * -+ * This code should not contain any messages; that requires an -+ * additional wrapper. -+ * -+ * As written, this code is not safe for inclusion into the kernel -+ * proper (after FPU initialization, in particular). -+ */ -+ -+#ifdef _SETUP -+# include "boot.h" -+# include "bitops.h" -+#endif -+#include -+#include -+#include -+#include -+#include -+ -+struct cpu_features { -+ int level; -+ int model; -+ u32 flags[NCAPINTS]; -+}; -+ -+static struct cpu_features cpu; -+static u32 cpu_vendor[3]; -+static u32 err_flags[NCAPINTS]; -+ -+#ifdef CONFIG_X86_64 -+static const int req_level = 64; -+#elif defined(CONFIG_X86_MINIMUM_CPU_MODEL) -+static const int req_level = CONFIG_X86_MINIMUM_CPU_MODEL; -+#else -+static const int req_level = 3; -+#endif -+ -+static const u32 req_flags[NCAPINTS] = -+{ -+ REQUIRED_MASK0, -+ REQUIRED_MASK1, -+ REQUIRED_MASK2, -+ REQUIRED_MASK3, -+ REQUIRED_MASK4, -+ REQUIRED_MASK5, -+ REQUIRED_MASK6, -+}; -+ -+#define A32(a,b,c,d) (((d) << 24)+((c) << 16)+((b) << 8)+(a)) -+ -+static int is_amd(void) -+{ -+ return cpu_vendor[0] == A32('A','u','t','h') && -+ cpu_vendor[1] == A32('e','n','t','i') && -+ cpu_vendor[2] == A32('c','A','M','D'); -+} -+ -+static int is_centaur(void) -+{ -+ return cpu_vendor[0] == A32('C','e','n','t') && -+ cpu_vendor[1] == A32('a','u','r','H') && -+ cpu_vendor[2] == A32('a','u','l','s'); -+} -+ -+static int is_transmeta(void) -+{ -+ return cpu_vendor[0] == A32('G','e','n','u') && -+ cpu_vendor[1] == A32('i','n','e','T') && -+ cpu_vendor[2] == A32('M','x','8','6'); -+} -+ -+static int has_fpu(void) -+{ -+ u16 fcw = -1, fsw = -1; -+ u32 cr0; -+ -+ asm("movl %%cr0,%0" : "=r" (cr0)); -+ if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { -+ cr0 &= ~(X86_CR0_EM|X86_CR0_TS); -+ asm volatile("movl %0,%%cr0" : : "r" (cr0)); -+ } -+ -+ asm("fninit ; fnstsw %0 ; fnstcw %1" : "+m" (fsw), "+m" (fcw)); -+ -+ return fsw == 0 && (fcw & 0x103f) == 0x003f; -+} -+ -+static int has_eflag(u32 mask) -+{ -+ u32 f0, f1; -+ -+ asm("pushfl ; " -+ "pushfl ; " -+ "popl %0 ; " -+ "movl %0,%1 ; " -+ "xorl %2,%1 ; " -+ "pushl %1 ; " -+ "popfl ; " -+ "pushfl ; " -+ "popl %1 ; " -+ "popfl" -+ : "=r" (f0), "=r" (f1) -+ : "g" (mask)); -+ -+ return !!((f0^f1) & mask); -+} -+ -+static void get_flags(void) -+{ -+ u32 max_intel_level, max_amd_level; -+ u32 tfms; -+ -+ if (has_fpu()) -+ set_bit(X86_FEATURE_FPU, cpu.flags); -+ -+ if (has_eflag(X86_EFLAGS_ID)) { -+ asm("cpuid" -+ : "=a" (max_intel_level), -+ "=b" (cpu_vendor[0]), -+ "=d" (cpu_vendor[1]), -+ "=c" (cpu_vendor[2]) -+ : "a" (0)); -+ -+ if (max_intel_level >= 0x00000001 && -+ max_intel_level <= 0x0000ffff) { -+ asm("cpuid" -+ : "=a" (tfms), -+ "=c" (cpu.flags[4]), -+ "=d" (cpu.flags[0]) -+ : "a" (0x00000001) -+ : "ebx"); -+ cpu.level = (tfms >> 8) & 15; -+ cpu.model = (tfms >> 4) & 15; -+ if (cpu.level >= 6) -+ cpu.model += ((tfms >> 16) & 0xf) << 4; -+ } -+ -+ asm("cpuid" -+ : "=a" (max_amd_level) -+ : "a" (0x80000000) -+ : "ebx", "ecx", "edx"); -+ -+ if (max_amd_level >= 0x80000001 && -+ max_amd_level <= 0x8000ffff) { -+ u32 eax = 0x80000001; -+ asm("cpuid" -+ : "+a" (eax), -+ "=c" (cpu.flags[6]), -+ "=d" (cpu.flags[1]) -+ : : "ebx"); -+ } -+ } -+} -+ -+/* Returns a bitmask of which words we have error bits in */ -+static int check_flags(void) -+{ -+ u32 err; -+ int i; -+ -+ err = 0; -+ for (i = 0; i < NCAPINTS; i++) { -+ err_flags[i] = req_flags[i] & ~cpu.flags[i]; -+ if (err_flags[i]) -+ err |= 1 << i; -+ } -+ -+ return err; -+} -+ -+/* -+ * Returns -1 on error. -+ * -+ * *cpu_level is set to the current CPU level; *req_level to the required -+ * level. x86-64 is considered level 64 for this purpose. -+ * -+ * *err_flags_ptr is set to the flags error array if there are flags missing. -+ */ -+int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr) -+{ -+ int err; -+ -+ memset(&cpu.flags, 0, sizeof cpu.flags); -+ cpu.level = 3; -+ -+ if (has_eflag(X86_EFLAGS_AC)) -+ cpu.level = 4; -+ -+ get_flags(); -+ err = check_flags(); -+ -+ if (test_bit(X86_FEATURE_LM, cpu.flags)) -+ cpu.level = 64; -+ -+ if (err == 0x01 && -+ !(err_flags[0] & -+ ~((1 << X86_FEATURE_XMM)|(1 << X86_FEATURE_XMM2))) && -+ is_amd()) { -+ /* If this is an AMD and we're only missing SSE+SSE2, try to -+ turn them on */ -+ -+ u32 ecx = MSR_K7_HWCR; -+ u32 eax, edx; -+ -+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); -+ eax &= ~(1 << 15); -+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); -+ -+ get_flags(); /* Make sure it really did something */ -+ err = check_flags(); -+ } else if (err == 0x01 && -+ !(err_flags[0] & ~(1 << X86_FEATURE_CX8)) && -+ is_centaur() && cpu.model >= 6) { -+ /* If this is a VIA C3, we might have to enable CX8 -+ explicitly */ -+ -+ u32 ecx = MSR_VIA_FCR; -+ u32 eax, edx; -+ -+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); -+ eax |= (1<<1)|(1<<7); -+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); -+ -+ set_bit(X86_FEATURE_CX8, cpu.flags); -+ err = check_flags(); -+ } else if (err == 0x01 && is_transmeta()) { -+ /* Transmeta might have masked feature bits in word 0 */ -+ -+ u32 ecx = 0x80860004; -+ u32 eax, edx; -+ u32 level = 1; -+ -+ asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); -+ asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); -+ asm("cpuid" -+ : "+a" (level), "=d" (cpu.flags[0]) -+ : : "ecx", "ebx"); -+ asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); -+ -+ err = check_flags(); -+ } -+ -+ if (err_flags_ptr) -+ *err_flags_ptr = err ? err_flags : NULL; -+ if (cpu_level_ptr) -+ *cpu_level_ptr = cpu.level; -+ if (req_level_ptr) -+ *req_level_ptr = req_level; -+ -+ return (cpu.level < req_level || err) ? -1 : 0; -+} ---- a/arch/i386/boot/edd.S -+++ /dev/null -@@ -1,231 +0,0 @@ --/* -- * BIOS Enhanced Disk Drive support -- * Copyright (C) 2002, 2003, 2004 Dell, Inc. -- * by Matt Domsch October 2002 -- * conformant to T13 Committee www.t13.org -- * projects 1572D, 1484D, 1386D, 1226DT -- * disk signature read by Matt Domsch -- * and Andrew Wilks September 2003, June 2004 -- * legacy CHS retrieval by Patrick J. LoPresti -- * March 2004 -- * Command line option parsing, Matt Domsch, November 2004 -- */ -- --#include --#include -- --#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) -- --# It is assumed that %ds == INITSEG here -- -- movb $0, (EDD_MBR_SIG_NR_BUF) -- movb $0, (EDDNR) -- --# Check the command line for options: --# edd=of disables EDD completely (edd=off) --# edd=sk skips the MBR test (edd=skipmbr) --# edd=on re-enables EDD (edd=on) -- -- pushl %esi -- movw $edd_mbr_sig_start, %di # Default to edd=on -- -- movl %cs:(cmd_line_ptr), %esi -- andl %esi, %esi -- jz old_cl # Old boot protocol? -- --# Convert to a real-mode pointer in fs:si -- movl %esi, %eax -- shrl $4, %eax -- movw %ax, %fs -- andw $0xf, %si -- jmp have_cl_pointer -- --# Old-style boot protocol? --old_cl: -- push %ds # aka INITSEG -- pop %fs -- -- cmpw $0xa33f, (0x20) -- jne done_cl # No command line at all? -- movw (0x22), %si # Pointer relative to INITSEG -- --# fs:si has the pointer to the command line now --have_cl_pointer: -- --# Loop through kernel command line one byte at a time. Just in --# case the loader is buggy and failed to null-terminate the command line --# terminate if we get close enough to the end of the segment that we --# cannot fit "edd=XX"... --cl_atspace: -- cmpw $-5, %si # Watch for segment wraparound -- jae done_cl -- movl %fs:(%si), %eax -- andb %al, %al # End of line? -- jz done_cl -- cmpl $EDD_CL_EQUALS, %eax -- jz found_edd_equals -- cmpb $0x20, %al # <= space consider whitespace -- ja cl_skipword -- incw %si -- jmp cl_atspace -- --cl_skipword: -- cmpw $-5, %si # Watch for segment wraparound -- jae done_cl -- movb %fs:(%si), %al # End of string? -- andb %al, %al -- jz done_cl -- cmpb $0x20, %al -- jbe cl_atspace -- incw %si -- jmp cl_skipword -- --found_edd_equals: --# only looking at first two characters after equals --# late overrides early on the command line, so keep going after finding something -- movw %fs:4(%si), %ax -- cmpw $EDD_CL_OFF, %ax # edd=of -- je do_edd_off -- cmpw $EDD_CL_SKIP, %ax # edd=sk -- je do_edd_skipmbr -- cmpw $EDD_CL_ON, %ax # edd=on -- je do_edd_on -- jmp cl_skipword --do_edd_skipmbr: -- movw $edd_start, %di -- jmp cl_skipword --do_edd_off: -- movw $edd_done, %di -- jmp cl_skipword --do_edd_on: -- movw $edd_mbr_sig_start, %di -- jmp cl_skipword -- --done_cl: -- popl %esi -- jmpw *%di -- --# Read the first sector of each BIOS disk device and store the 4-byte signature --edd_mbr_sig_start: -- movb $0x80, %dl # from device 80 -- movw $EDD_MBR_SIG_BUF, %bx # store buffer ptr in bx --edd_mbr_sig_read: -- movl $0xFFFFFFFF, %eax -- movl %eax, (%bx) # assume failure -- pushw %bx -- movb $READ_SECTORS, %ah -- movb $1, %al # read 1 sector -- movb $0, %dh # at head 0 -- movw $1, %cx # cylinder 0, sector 0 -- pushw %es -- pushw %ds -- popw %es -- movw $EDDBUF, %bx # disk's data goes into EDDBUF -- pushw %dx # work around buggy BIOSes -- stc # work around buggy BIOSes -- int $0x13 -- sti # work around buggy BIOSes -- popw %dx -- popw %es -- popw %bx -- jc edd_mbr_sig_done # on failure, we're done. -- cmpb $0, %ah # some BIOSes do not set CF -- jne edd_mbr_sig_done # on failure, we're done. -- movl (EDDBUF+EDD_MBR_SIG_OFFSET), %eax # read sig out of the MBR -- movl %eax, (%bx) # store success -- incb (EDD_MBR_SIG_NR_BUF) # note that we stored something -- incb %dl # increment to next device -- addw $4, %bx # increment sig buffer ptr -- cmpb $EDD_MBR_SIG_MAX, (EDD_MBR_SIG_NR_BUF) # Out of space? -- jb edd_mbr_sig_read # keep looping --edd_mbr_sig_done: -- --# Do the BIOS Enhanced Disk Drive calls --# This consists of two calls: --# int 13h ah=41h "Check Extensions Present" --# int 13h ah=48h "Get Device Parameters" --# int 13h ah=08h "Legacy Get Device Parameters" --# --# A buffer of size EDDMAXNR*(EDDEXTSIZE+EDDPARMSIZE) is reserved for our use --# in the boot_params at EDDBUF. The first four bytes of which are --# used to store the device number, interface support map and version --# results from fn41. The next four bytes are used to store the legacy --# cylinders, heads, and sectors from fn08. The following 74 bytes are used to --# store the results from fn48. Starting from device 80h, fn41, then fn48 --# are called and their results stored in EDDBUF+n*(EDDEXTSIZE+EDDPARMIZE). --# Then the pointer is incremented to store the data for the next call. --# This repeats until either a device doesn't exist, or until EDDMAXNR --# devices have been stored. --# The one tricky part is that ds:si always points EDDEXTSIZE bytes into --# the structure, and the fn41 and fn08 results are stored at offsets --# from there. This removes the need to increment the pointer for --# every store, and leaves it ready for the fn48 call. --# A second one-byte buffer, EDDNR, in the boot_params stores --# the number of BIOS devices which exist, up to EDDMAXNR. --# In setup.c, copy_edd() stores both boot_params buffers away --# for later use, as they would get overwritten otherwise. --# This code is sensitive to the size of the structs in edd.h --edd_start: -- # %ds points to the bootsector -- # result buffer for fn48 -- movw $EDDBUF+EDDEXTSIZE, %si # in ds:si, fn41 results -- # kept just before that -- movb $0x80, %dl # BIOS device 0x80 -- --edd_check_ext: -- movb $CHECKEXTENSIONSPRESENT, %ah # Function 41 -- movw $EDDMAGIC1, %bx # magic -- int $0x13 # make the call -- jc edd_done # no more BIOS devices -- -- cmpw $EDDMAGIC2, %bx # is magic right? -- jne edd_next # nope, next... -- -- movb %dl, %ds:-8(%si) # store device number -- movb %ah, %ds:-7(%si) # store version -- movw %cx, %ds:-6(%si) # store extensions -- incb (EDDNR) # note that we stored something -- --edd_get_device_params: -- movw $EDDPARMSIZE, %ds:(%si) # put size -- movw $0x0, %ds:2(%si) # work around buggy BIOSes -- movb $GETDEVICEPARAMETERS, %ah # Function 48 -- int $0x13 # make the call -- # Don't check for fail return -- # it doesn't matter. --edd_get_legacy_chs: -- xorw %ax, %ax -- movw %ax, %ds:-4(%si) -- movw %ax, %ds:-2(%si) -- # Ralf Brown's Interrupt List says to set ES:DI to -- # 0000h:0000h "to guard against BIOS bugs" -- pushw %es -- movw %ax, %es -- movw %ax, %di -- pushw %dx # legacy call clobbers %dl -- movb $LEGACYGETDEVICEPARAMETERS, %ah # Function 08 -- int $0x13 # make the call -- jc edd_legacy_done # failed -- movb %cl, %al # Low 6 bits are max -- andb $0x3F, %al # sector number -- movb %al, %ds:-1(%si) # Record max sect -- movb %dh, %ds:-2(%si) # Record max head number -- movb %ch, %al # Low 8 bits of max cyl -- shr $6, %cl -- movb %cl, %ah # High 2 bits of max cyl -- movw %ax, %ds:-4(%si) -- --edd_legacy_done: -- popw %dx -- popw %es -- movw %si, %ax # increment si -- addw $EDDPARMSIZE+EDDEXTSIZE, %ax -- movw %ax, %si -- --edd_next: -- incb %dl # increment to next device -- cmpb $EDDMAXNR, (EDDNR) # Out of space? -- jb edd_check_ext # keep looping -- --edd_done: --#endif ---- /dev/null -+++ b/arch/i386/boot/edd.c -@@ -0,0 +1,196 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/edd.c -+ * -+ * Get EDD BIOS disk information -+ */ -+ -+#include "boot.h" -+#include -+ -+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) -+ -+struct edd_dapa { -+ u8 pkt_size; -+ u8 rsvd; -+ u16 sector_cnt; -+ u16 buf_off, buf_seg; -+ u64 lba; -+ u64 buf_lin_addr; -+}; -+ -+/* -+ * Note: this uses the heap to hold the loaded sector. -+ */ -+static int read_sector(u8 devno, u64 lba, void *buf) -+{ -+ struct edd_dapa dapa; -+ u16 ax, bx, cx, dx, si; -+ -+ memset(&dapa, 0, sizeof dapa); -+ dapa.pkt_size = sizeof(dapa); -+ dapa.sector_cnt = 1; -+ dapa.buf_off = (size_t)buf; -+ dapa.buf_seg = ds(); -+ dapa.lba = lba; -+ -+ ax = 0x4200; /* Extended Read */ -+ si = (size_t)&dapa; -+ dx = devno; -+ asm("pushfl; stc; int $0x13; setc %%al; popfl" -+ : "+a" (ax), "+S" (si), "+d" (dx) -+ : "m" (dapa) -+ : "ebx", "ecx", "edi", "memory"); -+ -+ if (!(u8)ax) -+ return 0; /* OK */ -+ -+ ax = 0x0201; /* Legacy Read, one sector */ -+ cx = 0x0001; /* Sector 0-0-1 */ -+ dx = devno; -+ bx = (size_t)buf; -+ asm("pushfl; stc; int $0x13; setc %%al; popfl" -+ : "+a" (ax), "+c" (cx), "+d" (dx), "+b" (bx) -+ : : "esi", "edi", "memory"); -+ -+ return -(u8)ax; /* 0 or -1 */ -+} -+ -+static u32 read_mbr_sig(u8 devno, struct edd_info *ei) -+{ -+ int sector_size; -+ char *mbrbuf_ptr, *mbrbuf_end; -+ u32 mbrsig; -+ u32 buf_base, mbr_base; -+ extern char _end[]; -+ static char mbr_buf[1024]; -+ -+ sector_size = ei->params.bytes_per_sector; -+ if (!sector_size) -+ sector_size = 512; /* Best available guess */ -+ -+ buf_base = (ds() << 4) + (u32)&_end; -+ mbr_base = (buf_base+sector_size-1) & ~(sector_size-1); -+ mbrbuf_ptr = mbr_buf + (mbr_base-buf_base); -+ mbrbuf_end = mbrbuf_ptr + sector_size; -+ -+ if (!(boot_params.hdr.loadflags & CAN_USE_HEAP)) -+ return 0; -+ if (mbrbuf_end > (char *)(size_t)boot_params.hdr.heap_end_ptr) -+ return 0; -+ -+ if (read_sector(devno, 0, mbrbuf_ptr)) -+ return 0; -+ -+ mbrsig = *(u32 *)&mbrbuf_ptr[EDD_MBR_SIG_OFFSET]; -+ return mbrsig; -+} -+ -+static int get_edd_info(u8 devno, struct edd_info *ei) -+{ -+ u16 ax, bx, cx, dx, di; -+ -+ memset(ei, 0, sizeof *ei); -+ -+ /* Check Extensions Present */ -+ -+ ax = 0x4100; -+ bx = EDDMAGIC1; -+ dx = devno; -+ asm("pushfl; stc; int $0x13; setc %%al; popfl" -+ : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) -+ : : "esi", "edi"); -+ -+ if ((u8)ax) -+ return -1; /* No extended information */ -+ -+ if (bx != EDDMAGIC2) -+ return -1; -+ -+ ei->device = devno; -+ ei->version = ax >> 8; /* EDD version number */ -+ ei->interface_support = cx; /* EDD functionality subsets */ -+ -+ /* Extended Get Device Parameters */ -+ -+ ei->params.length = sizeof(ei->params); -+ ax = 0x4800; -+ dx = devno; -+ asm("pushfl; int $0x13; popfl" -+ : "+a" (ax), "+d" (dx) -+ : "S" (&ei->params) -+ : "ebx", "ecx", "edi"); -+ -+ /* Get legacy CHS parameters */ -+ -+ /* Ralf Brown recommends setting ES:DI to 0:0 */ -+ ax = 0x0800; -+ dx = devno; -+ di = 0; -+ asm("pushw %%es; " -+ "movw %%di,%%es; " -+ "pushfl; stc; int $0x13; setc %%al; popfl; " -+ "popw %%es" -+ : "+a" (ax), "=b" (bx), "=c" (cx), "+d" (dx), "+D" (di) -+ : : "esi"); -+ -+ if ((u8)ax == 0) { -+ ei->legacy_max_cylinder = (cx >> 8) + ((cx & 0xc0) << 2); -+ ei->legacy_max_head = dx >> 8; -+ ei->legacy_sectors_per_track = cx & 0x3f; -+ } -+ -+ return 0; -+} -+ -+void query_edd(void) -+{ -+ char eddarg[8]; -+ int do_mbr = 1; -+ int do_edd = 1; -+ int devno; -+ struct edd_info ei, *edp; -+ -+ if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) { -+ if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) -+ do_mbr = 0; -+ else if (!strcmp(eddarg, "off")) -+ do_edd = 0; -+ } -+ -+ edp = (struct edd_info *)boot_params.eddbuf; -+ -+ if (!do_edd) -+ return; -+ -+ for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) { -+ /* -+ * Scan the BIOS-supported hard disks and query EDD -+ * information... -+ */ -+ get_edd_info(devno, &ei); -+ -+ if (boot_params.eddbuf_entries < EDDMAXNR) { -+ memcpy(edp, &ei, sizeof ei); -+ edp++; -+ boot_params.eddbuf_entries++; -+ } -+ -+ if (do_mbr) { -+ u32 mbr_sig; -+ mbr_sig = read_mbr_sig(devno, &ei); -+ boot_params.edd_mbr_sig_buffer[devno-0x80] = mbr_sig; -+ } -+ } -+} -+ -+#endif ---- /dev/null -+++ b/arch/i386/boot/header.S -@@ -0,0 +1,283 @@ -+/* -+ * header.S -+ * -+ * Copyright (C) 1991, 1992 Linus Torvalds -+ * -+ * Based on bootsect.S and setup.S -+ * modified by more people than can be counted -+ * -+ * Rewritten as a common file by H. Peter Anvin (Apr 2007) -+ * -+ * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment -+ * addresses must be multiplied by 16 to obtain their respective linear -+ * addresses. To avoid confusion, linear addresses are written using leading -+ * hex while segment addresses are written as segment:offset. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "boot.h" -+ -+SETUPSECTS = 4 /* default nr of setup-sectors */ -+BOOTSEG = 0x07C0 /* original address of boot-sector */ -+SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ -+SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ -+ /* to be loaded */ -+ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ -+SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ -+ -+#ifndef SVGA_MODE -+#define SVGA_MODE ASK_VGA -+#endif -+ -+#ifndef RAMDISK -+#define RAMDISK 0 -+#endif -+ -+#ifndef ROOT_RDONLY -+#define ROOT_RDONLY 1 -+#endif -+ -+ .code16 -+ .section ".bstext", "ax" -+ -+ .global bootsect_start -+bootsect_start: -+ -+ # Normalize the start address -+ ljmp $BOOTSEG, $start2 -+ -+start2: -+ movw %cs, %ax -+ movw %ax, %ds -+ movw %ax, %es -+ movw %ax, %ss -+ xorw %sp, %sp -+ sti -+ cld -+ -+ movw $bugger_off_msg, %si -+ -+msg_loop: -+ lodsb -+ andb %al, %al -+ jz bs_die -+ movb $0xe, %ah -+ movw $7, %bx -+ int $0x10 -+ jmp msg_loop -+ -+bs_die: -+ # Allow the user to press a key, then reboot -+ xorw %ax, %ax -+ int $0x16 -+ int $0x19 -+ -+ # int 0x19 should never return. In case it does anyway, -+ # invoke the BIOS reset code... -+ ljmp $0xf000,$0xfff0 -+ -+ .section ".bsdata", "a" -+bugger_off_msg: -+ .ascii "Direct booting from floppy is no longer supported.\r\n" -+ .ascii "Please use a boot loader program instead.\r\n" -+ .ascii "\n" -+ .ascii "Remove disk and press any key to reboot . . .\r\n" -+ .byte 0 -+ -+ -+ # Kernel attributes; used by setup. This is part 1 of the -+ # header, from the old boot sector. -+ -+ .section ".header", "a" -+ .globl hdr -+hdr: -+setup_sects: .byte SETUPSECTS -+root_flags: .word ROOT_RDONLY -+syssize: .long SYSSIZE -+ram_size: .word RAMDISK -+vid_mode: .word SVGA_MODE -+root_dev: .word ROOT_DEV -+boot_flag: .word 0xAA55 -+ -+ # offset 512, entry point -+ -+ .globl _start -+_start: -+ # Explicitly enter this as bytes, or the assembler -+ # tries to generate a 3-byte jump here, which causes -+ # everything else to push off to the wrong offset. -+ .byte 0xeb # short (2-byte) jump -+ .byte start_of_setup-1f -+1: -+ -+ # Part 2 of the header, from the old setup.S -+ -+ .ascii "HdrS" # header signature -+ .word 0x0206 # header version number (>= 0x0105) -+ # or else old loadlin-1.5 will fail) -+ .globl realmode_swtch -+realmode_swtch: .word 0, 0 # default_switch, SETUPSEG -+start_sys_seg: .word SYSSEG -+ .word kernel_version-512 # pointing to kernel version string -+ # above section of header is compatible -+ # with loadlin-1.5 (header v1.5). Don't -+ # change it. -+ -+type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, -+ # Bootlin, SYSLX, bootsect...) -+ # See Documentation/i386/boot.txt for -+ # assigned ids -+ -+# flags, unused bits must be zero (RFU) bit within loadflags -+loadflags: -+LOADED_HIGH = 1 # If set, the kernel is loaded high -+CAN_USE_HEAP = 0x80 # If set, the loader also has set -+ # heap_end_ptr to tell how much -+ # space behind setup.S can be used for -+ # heap purposes. -+ # Only the loader knows what is free -+#ifndef __BIG_KERNEL__ -+ .byte 0 -+#else -+ .byte LOADED_HIGH -+#endif -+ -+setup_move_size: .word 0x8000 # size to move, when setup is not -+ # loaded at 0x90000. We will move setup -+ # to 0x90000 then just before jumping -+ # into the kernel. However, only the -+ # loader knows how much data behind -+ # us also needs to be loaded. -+ -+code32_start: # here loaders can put a different -+ # start address for 32-bit code. -+#ifndef __BIG_KERNEL__ -+ .long 0x1000 # 0x1000 = default for zImage -+#else -+ .long 0x100000 # 0x100000 = default for big kernel -+#endif -+ -+ramdisk_image: .long 0 # address of loaded ramdisk image -+ # Here the loader puts the 32-bit -+ # address where it loaded the image. -+ # This only will be read by the kernel. -+ -+ramdisk_size: .long 0 # its size in bytes -+ -+bootsect_kludge: -+ .long 0 # obsolete -+ -+heap_end_ptr: .word _end+1024 # (Header version 0x0201 or later) -+ # space from here (exclusive) down to -+ # end of setup code can be used by setup -+ # for local heap purposes. -+ -+pad1: .word 0 -+cmd_line_ptr: .long 0 # (Header version 0x0202 or later) -+ # If nonzero, a 32-bit pointer -+ # to the kernel command line. -+ # The command line should be -+ # located between the start of -+ # setup and the end of low -+ # memory (0xa0000), or it may -+ # get overwritten before it -+ # gets read. If this field is -+ # used, there is no longer -+ # anything magical about the -+ # 0x90000 segment; the setup -+ # can be located anywhere in -+ # low memory 0x10000 or higher. -+ -+ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff -+ # (Header version 0x0203 or later) -+ # The highest safe address for -+ # the contents of an initrd -+ -+kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment -+ #required for protected mode -+ #kernel -+#ifdef CONFIG_RELOCATABLE -+relocatable_kernel: .byte 1 -+#else -+relocatable_kernel: .byte 0 -+#endif -+pad2: .byte 0 -+pad3: .word 0 -+ -+cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, -+ #added with boot protocol -+ #version 2.06 -+ -+# End of setup header ##################################################### -+ -+ .section ".inittext", "ax" -+start_of_setup: -+#ifdef SAFE_RESET_DISK_CONTROLLER -+# Reset the disk controller. -+ movw $0x0000, %ax # Reset disk controller -+ movb $0x80, %dl # All disks -+ int $0x13 -+#endif -+ -+# We will have entired with %cs = %ds+0x20, normalize %cs so -+# it is on par with the other segments. -+ pushw %ds -+ pushw $setup2 -+ lretw -+ -+setup2: -+# Force %es = %ds -+ movw %ds, %ax -+ movw %ax, %es -+ cld -+ -+# Stack paranoia: align the stack and make sure it is good -+# for both 16- and 32-bit references. In particular, if we -+# were meant to have been using the full 16-bit segment, the -+# caller might have set %sp to zero, which breaks %esp-based -+# references. -+ andw $~3, %sp # dword align (might as well...) -+ jnz 1f -+ movw $0xfffc, %sp # Make sure we're not zero -+1: movzwl %sp, %esp # Clear upper half of %esp -+ sti -+ -+# Check signature at end of setup -+ cmpl $0x5a5aaa55, setup_sig -+ jne setup_bad -+ -+# Zero the bss -+ movw $__bss_start, %di -+ movw $_end+3, %cx -+ xorl %eax, %eax -+ subw %di, %cx -+ shrw $2, %cx -+ rep; stosl -+ -+# Jump to C code (should not return) -+ calll main -+ -+# Setup corrupt somehow... -+setup_bad: -+ movl $setup_corrupt, %eax -+ calll puts -+ # Fall through... -+ -+ .globl die -+ .type die, @function -+die: -+ hlt -+ jmp die -+ -+ .size die, .-due -+ -+ .section ".initdata", "a" -+setup_corrupt: -+ .byte 7 -+ .string "No setup signature found..." ---- /dev/null -+++ b/arch/i386/boot/main.c -@@ -0,0 +1,161 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/main.c -+ * -+ * Main module for the real-mode kernel code -+ */ -+ -+#include "boot.h" -+ -+struct boot_params boot_params __attribute__((aligned(16))); -+ -+char *HEAP = _end; -+char *heap_end = _end; /* Default end of heap = no heap */ -+ -+/* -+ * Copy the header into the boot parameter block. Since this -+ * screws up the old-style command line protocol, adjust by -+ * filling in the new-style command line pointer instead. -+ */ -+#define OLD_CL_MAGIC 0xA33F -+#define OLD_CL_ADDRESS 0x20 -+ -+static void copy_boot_params(void) -+{ -+ struct old_cmdline { -+ u16 cl_magic; -+ u16 cl_offset; -+ }; -+ const struct old_cmdline * const oldcmd = -+ (const struct old_cmdline *)OLD_CL_ADDRESS; -+ -+ BUILD_BUG_ON(sizeof boot_params != 4096); -+ memcpy(&boot_params.hdr, &hdr, sizeof hdr); -+ -+ if (!boot_params.hdr.cmd_line_ptr && -+ oldcmd->cl_magic == OLD_CL_MAGIC) { -+ /* Old-style command line protocol. */ -+ u16 cmdline_seg; -+ -+ /* Figure out if the command line falls in the region -+ of memory that an old kernel would have copied up -+ to 0x90000... */ -+ if (oldcmd->cl_offset < boot_params.hdr.setup_move_size) -+ cmdline_seg = ds(); -+ else -+ cmdline_seg = 0x9000; -+ -+ boot_params.hdr.cmd_line_ptr = -+ (cmdline_seg << 4) + oldcmd->cl_offset; -+ } -+} -+ -+/* -+ * Set the keyboard repeat rate to maximum. Unclear why this -+ * is done here; this might be possible to kill off as stale code. -+ */ -+static void keyboard_set_repeat(void) -+{ -+ u16 ax = 0x0305; -+ u16 bx = 0; -+ asm volatile("int $0x16" -+ : "+a" (ax), "+b" (bx) -+ : : "ecx", "edx", "esi", "edi"); -+} -+ -+/* -+ * Get Intel SpeedStep IST information. -+ */ -+static void query_speedstep_ist(void) -+{ -+ asm("int $0x15" -+ : "=a" (boot_params.speedstep_info[0]), -+ "=b" (boot_params.speedstep_info[1]), -+ "=c" (boot_params.speedstep_info[2]), -+ "=d" (boot_params.speedstep_info[3]) -+ : "a" (0x0000e980), /* IST Support */ -+ "d" (0x47534943)); /* Request value */ -+} -+ -+/* -+ * Tell the BIOS what CPU mode we intend to run in. -+ */ -+static void set_bios_mode(void) -+{ -+#ifdef CONFIG_X86_64 -+ u32 eax, ebx; -+ -+ eax = 0xec00; -+ ebx = 2; -+ asm volatile("int $0x15" -+ : "+a" (eax), "+b" (ebx) -+ : : "ecx", "edx", "esi", "edi"); -+#endif -+} -+ -+void main(void) -+{ -+ /* First, copy the boot header into the "zeropage" */ -+ copy_boot_params(); -+ -+ /* End of heap check */ -+ if (boot_params.hdr.loadflags & CAN_USE_HEAP) { -+ heap_end = (char *)(boot_params.hdr.heap_end_ptr -+ +0x200-STACK_SIZE); -+ } else { -+ /* Boot protocol 2.00 only, no heap available */ -+ puts("WARNING: Ancient bootloader, some functionality " -+ "may be limited!\n"); -+ } -+ -+ /* Make sure we have all the proper CPU support */ -+ if (validate_cpu()) { -+ puts("Unable to boot - please use a kernel appropriate " -+ "for your CPU.\n"); -+ die(); -+ } -+ -+ /* Tell the BIOS what CPU mode we intend to run in. */ -+ set_bios_mode(); -+ -+ /* Detect memory layout */ -+ detect_memory(); -+ -+ /* Set keyboard repeat rate (why?) */ -+ keyboard_set_repeat(); -+ -+ /* Set the video mode */ -+ set_video(); -+ -+ /* Query MCA information */ -+ query_mca(); -+ -+ /* Voyager */ -+#ifdef CONFIG_X86_VOYAGER -+ query_voyager(); -+#endif -+ -+ /* Query SpeedStep IST information */ -+ query_speedstep_ist(); -+ -+ /* Query APM information */ -+#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) -+ query_apm_bios(); -+#endif -+ -+ /* Query EDD information */ -+#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) -+ query_edd(); -+#endif -+ /* Do the last things and invoke protected mode */ -+ go_to_protected_mode(); -+} ---- /dev/null -+++ b/arch/i386/boot/mca.c -@@ -0,0 +1,43 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/mca.c -+ * -+ * Get the MCA system description table -+ */ -+ -+#include "boot.h" -+ -+int query_mca(void) -+{ -+ u8 err; -+ u16 es, bx, len; -+ -+ asm("pushw %%es ; " -+ "int $0x15 ; " -+ "setc %0 ; " -+ "movw %%es, %1 ; " -+ "popw %%es" -+ : "=acdSDm" (err), "=acdSDm" (es), "=b" (bx) -+ : "a" (0xc000)); -+ -+ if (err) -+ return -1; /* No MCA present */ -+ -+ set_fs(es); -+ len = rdfs16(bx); -+ -+ if (len > sizeof(boot_params.sys_desc_table)) -+ len = sizeof(boot_params.sys_desc_table); -+ -+ copy_from_fs(&boot_params.sys_desc_table, bx, len); -+ return 0; -+} ---- /dev/null -+++ b/arch/i386/boot/memory.c -@@ -0,0 +1,99 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/memory.c -+ * -+ * Memory detection code -+ */ -+ -+#include "boot.h" -+ -+#define SMAP 0x534d4150 /* ASCII "SMAP" */ -+ -+static int detect_memory_e820(void) -+{ -+ u32 next = 0; -+ u32 size, id; -+ u8 err; -+ struct e820entry *desc = boot_params.e820_map; -+ -+ do { -+ size = sizeof(struct e820entry); -+ id = SMAP; -+ asm("int $0x15; setc %0" -+ : "=am" (err), "+b" (next), "+d" (id), "+c" (size), -+ "=m" (*desc) -+ : "D" (desc), "a" (0xe820)); -+ -+ if (err || id != SMAP) -+ break; -+ -+ boot_params.e820_entries++; -+ desc++; -+ } while (next && boot_params.e820_entries < E820MAX); -+ -+ return boot_params.e820_entries; -+} -+ -+static int detect_memory_e801(void) -+{ -+ u16 ax, bx, cx, dx; -+ u8 err; -+ -+ bx = cx = dx = 0; -+ ax = 0xe801; -+ asm("stc; int $0x15; setc %0" -+ : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx)); -+ -+ if (err) -+ return -1; -+ -+ /* Do we really need to do this? */ -+ if (cx || dx) { -+ ax = cx; -+ bx = dx; -+ } -+ -+ if (ax > 15*1024) -+ return -1; /* Bogus! */ -+ -+ /* This ignores memory above 16MB if we have a memory hole -+ there. If someone actually finds a machine with a memory -+ hole at 16MB and no support for 0E820h they should probably -+ generate a fake e820 map. */ -+ boot_params.alt_mem_k = (ax == 15*1024) ? (dx << 6)+ax : ax; -+ -+ return 0; -+} -+ -+static int detect_memory_88(void) -+{ -+ u16 ax; -+ u8 err; -+ -+ ax = 0x8800; -+ asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); -+ -+ boot_params.screen_info.ext_mem_k = ax; -+ -+ return -err; -+} -+ -+int detect_memory(void) -+{ -+ if (detect_memory_e820() > 0) -+ return 0; -+ -+ if (!detect_memory_e801()) -+ return 0; -+ -+ return detect_memory_88(); -+} ---- /dev/null -+++ b/arch/i386/boot/pm.c -@@ -0,0 +1,170 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/pm.c -+ * -+ * Prepare the machine for transition to protected mode. -+ */ -+ -+#include "boot.h" -+#include -+ -+/* -+ * Invoke the realmode switch hook if present; otherwise -+ * disable all interrupts. -+ */ -+static void realmode_switch_hook(void) -+{ -+ if (boot_params.hdr.realmode_swtch) { -+ asm volatile("lcallw *%0" -+ : : "m" (boot_params.hdr.realmode_swtch) -+ : "eax", "ebx", "ecx", "edx"); -+ } else { -+ asm volatile("cli"); -+ outb(0x80, 0x70); /* Disable NMI */ -+ io_delay(); -+ } -+} -+ -+/* -+ * A zImage kernel is loaded at 0x10000 but wants to run at 0x1000. -+ * A bzImage kernel is loaded and runs at 0x100000. -+ */ -+static void move_kernel_around(void) -+{ -+ /* Note: rely on the compile-time option here rather than -+ the LOADED_HIGH flag. The Qemu kernel loader unconditionally -+ sets the loadflags to zero. */ -+#ifndef __BIG_KERNEL__ -+ u16 dst_seg, src_seg; -+ u32 syssize; -+ -+ dst_seg = 0x1000 >> 4; -+ src_seg = 0x10000 >> 4; -+ syssize = boot_params.hdr.syssize; /* Size in 16-byte paragraps */ -+ -+ while (syssize) { -+ int paras = (syssize >= 0x1000) ? 0x1000 : syssize; -+ int dwords = paras << 2; -+ -+ asm volatile("pushw %%es ; " -+ "pushw %%ds ; " -+ "movw %1,%%es ; " -+ "movw %2,%%ds ; " -+ "xorw %%di,%%di ; " -+ "xorw %%si,%%si ; " -+ "rep;movsl ; " -+ "popw %%ds ; " -+ "popw %%es" -+ : "+c" (dwords) -+ : "rm" (dst_seg), "rm" (src_seg) -+ : "esi", "edi"); -+ -+ syssize -= paras; -+ dst_seg += paras; -+ src_seg += paras; -+ } -+#endif -+} -+ -+/* -+ * Disable all interrupts at the legacy PIC. -+ */ -+static void mask_all_interrupts(void) -+{ -+ outb(0xff, 0xa1); /* Mask all interrupts on the seconday PIC */ -+ io_delay(); -+ outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */ -+ io_delay(); -+} -+ -+/* -+ * Reset IGNNE# if asserted in the FPU. -+ */ -+static void reset_coprocessor(void) -+{ -+ outb(0, 0xf0); -+ io_delay(); -+ outb(0, 0xf1); -+ io_delay(); -+} -+ -+/* -+ * Set up the GDT -+ */ -+#define GDT_ENTRY(flags,base,limit) \ -+ (((u64)(base & 0xff000000) << 32) | \ -+ ((u64)flags << 40) | \ -+ ((u64)(limit & 0x00ff0000) << 32) | \ -+ ((u64)(base & 0x00ffff00) << 16) | \ -+ ((u64)(limit & 0x0000ffff))) -+ -+struct gdt_ptr { -+ u16 len; -+ u32 ptr; -+} __attribute__((packed)); -+ -+static void setup_gdt(void) -+{ -+ /* There are machines which are known to not boot with the GDT -+ being 8-byte unaligned. Intel recommends 16 byte alignment. */ -+ static const u64 boot_gdt[] __attribute__((aligned(16))) = { -+ /* 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), -+ }; -+ struct gdt_ptr gdt; -+ -+ gdt.len = sizeof(boot_gdt)-1; -+ gdt.ptr = (u32)&boot_gdt + (ds() << 4); -+ -+ asm volatile("lgdtl %0" : : "m" (gdt)); -+} -+ -+/* -+ * Set up the IDT -+ */ -+static void setup_idt(void) -+{ -+ static const struct gdt_ptr null_idt = {0, 0}; -+ asm volatile("lidtl %0" : : "m" (null_idt)); -+} -+ -+/* -+ * Actual invocation sequence -+ */ -+void go_to_protected_mode(void) -+{ -+ /* Hook before leaving real mode, also disables interrupts */ -+ realmode_switch_hook(); -+ -+ /* Move the kernel/setup to their final resting places */ -+ move_kernel_around(); -+ -+ /* Enable the A20 gate */ -+ if (enable_a20()) { -+ puts("A20 gate not responding, unable to boot...\n"); -+ die(); -+ } -+ -+ /* Reset coprocessor (IGNNE#) */ -+ reset_coprocessor(); -+ -+ /* Mask all interrupts in the PIC */ -+ mask_all_interrupts(); -+ -+ /* Actual transition to protected mode... */ -+ setup_idt(); -+ setup_gdt(); -+ protected_mode_jump(boot_params.hdr.code32_start, -+ (u32)&boot_params + (ds() << 4)); -+} ---- /dev/null -+++ b/arch/i386/boot/pmjump.S -@@ -0,0 +1,54 @@ -+/* ----------------------------------------------------------------------- * -+ * -+ * 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/pmjump.S -+ * -+ * The actual transition into protected mode -+ */ -+ -+#include -+#include -+ -+ .text -+ -+ .globl protected_mode_jump -+ .type protected_mode_jump, @function -+ -+ .code16 -+ -+/* -+ * void protected_mode_jump(u32 entrypoint, u32 bootparams); -+ */ -+protected_mode_jump: -+ xorl %ebx, %ebx # Flag to indicate this is a boot -+ movl %edx, %esi # Pointer to boot_params table -+ movl %eax, 2f # Patch ljmpl instruction -+ jmp 1f # Short jump to flush instruction q. -+ -+1: -+ movw $__BOOT_DS, %cx -+ -+ movl %cr0, %edx -+ orb $1, %dl # Protected mode (PE) bit -+ movl %edx, %cr0 -+ -+ movw %cx, %ds -+ movw %cx, %es -+ movw %cx, %fs -+ movw %cx, %gs -+ movw %cx, %ss -+ -+ # Jump to the 32-bit entrypoint -+ .byte 0x66, 0xea # ljmpl opcode -+2: .long 0 # offset -+ .word __BOOT_CS # segment -+ -+ .size protected_mode_jump, .-protected_mode_jump ---- /dev/null -+++ b/arch/i386/boot/printf.c -@@ -0,0 +1,331 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/printf.c -+ * -+ * Oh, it's a waste of space, but oh-so-yummy for debugging. This -+ * version of printf() does not include 64-bit support. "Live with -+ * it." -+ * -+ */ -+ -+#include "boot.h" -+ -+static inline int isdigit(int ch) -+{ -+ return (ch >= '0') && (ch <= '9'); -+} -+ -+static int skip_atoi(const char **s) -+{ -+ int i = 0; -+ -+ while (isdigit(**s)) -+ i = i * 10 + *((*s)++) - '0'; -+ return i; -+} -+ -+unsigned int atou(const char *s) -+{ -+ unsigned int i = 0; -+ while (isdigit(*s)) -+ i = i * 10 + (*s++ - '0'); -+ return i; -+} -+ -+static int strnlen(const char *s, int maxlen) -+{ -+ const char *es = s; -+ while (*es && maxlen) { -+ es++; -+ maxlen--; -+ } -+ -+ return (es - s); -+} -+ -+#define ZEROPAD 1 /* pad with zero */ -+#define SIGN 2 /* unsigned/signed long */ -+#define PLUS 4 /* show plus */ -+#define SPACE 8 /* space if plus */ -+#define LEFT 16 /* left justified */ -+#define SPECIAL 32 /* 0x */ -+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -+ -+#define do_div(n,base) ({ \ -+int __res; \ -+__res = ((unsigned long) n) % (unsigned) base; \ -+n = ((unsigned long) n) / (unsigned) base; \ -+__res; }) -+ -+static char *number(char *str, long num, int base, int size, int precision, -+ int type) -+{ -+ char c, sign, tmp[66]; -+ const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz"; -+ int i; -+ -+ if (type & LARGE) -+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -+ if (type & LEFT) -+ type &= ~ZEROPAD; -+ if (base < 2 || base > 36) -+ return 0; -+ c = (type & ZEROPAD) ? '0' : ' '; -+ sign = 0; -+ if (type & SIGN) { -+ if (num < 0) { -+ sign = '-'; -+ num = -num; -+ size--; -+ } else if (type & PLUS) { -+ sign = '+'; -+ size--; -+ } else if (type & SPACE) { -+ sign = ' '; -+ size--; -+ } -+ } -+ if (type & SPECIAL) { -+ if (base == 16) -+ size -= 2; -+ else if (base == 8) -+ size--; -+ } -+ i = 0; -+ if (num == 0) -+ tmp[i++] = '0'; -+ else -+ while (num != 0) -+ tmp[i++] = digits[do_div(num, base)]; -+ if (i > precision) -+ precision = i; -+ size -= precision; -+ if (!(type & (ZEROPAD + LEFT))) -+ while (size-- > 0) -+ *str++ = ' '; -+ if (sign) -+ *str++ = sign; -+ if (type & SPECIAL) { -+ if (base == 8) -+ *str++ = '0'; -+ else if (base == 16) { -+ *str++ = '0'; -+ *str++ = digits[33]; -+ } -+ } -+ if (!(type & LEFT)) -+ while (size-- > 0) -+ *str++ = c; -+ while (i < precision--) -+ *str++ = '0'; -+ while (i-- > 0) -+ *str++ = tmp[i]; -+ while (size-- > 0) -+ *str++ = ' '; -+ return str; -+} -+ -+int vsprintf(char *buf, const char *fmt, va_list args) -+{ -+ int len; -+ unsigned long num; -+ int i, base; -+ char *str; -+ const char *s; -+ -+ int flags; /* flags to number() */ -+ -+ int field_width; /* width of output field */ -+ int precision; /* min. # of digits for integers; max -+ number of chars for from string */ -+ int qualifier; /* 'h', 'l', or 'L' for integer fields */ -+ -+ for (str = buf; *fmt; ++fmt) { -+ if (*fmt != '%') { -+ *str++ = *fmt; -+ continue; -+ } -+ -+ /* process flags */ -+ flags = 0; -+ repeat: -+ ++fmt; /* this also skips first '%' */ -+ switch (*fmt) { -+ case '-': -+ flags |= LEFT; -+ goto repeat; -+ case '+': -+ flags |= PLUS; -+ goto repeat; -+ case ' ': -+ flags |= SPACE; -+ goto repeat; -+ case '#': -+ flags |= SPECIAL; -+ goto repeat; -+ case '0': -+ flags |= ZEROPAD; -+ goto repeat; -+ } -+ -+ /* get field width */ -+ field_width = -1; -+ if (isdigit(*fmt)) -+ field_width = skip_atoi(&fmt); -+ else if (*fmt == '*') { -+ ++fmt; -+ /* it's the next argument */ -+ field_width = va_arg(args, int); -+ if (field_width < 0) { -+ field_width = -field_width; -+ flags |= LEFT; -+ } -+ } -+ -+ /* get the precision */ -+ precision = -1; -+ if (*fmt == '.') { -+ ++fmt; -+ if (isdigit(*fmt)) -+ precision = skip_atoi(&fmt); -+ else if (*fmt == '*') { -+ ++fmt; -+ /* it's the next argument */ -+ precision = va_arg(args, int); -+ } -+ if (precision < 0) -+ precision = 0; -+ } -+ -+ /* get the conversion qualifier */ -+ qualifier = -1; -+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { -+ qualifier = *fmt; -+ ++fmt; -+ } -+ -+ /* default base */ -+ base = 10; -+ -+ switch (*fmt) { -+ case 'c': -+ if (!(flags & LEFT)) -+ while (--field_width > 0) -+ *str++ = ' '; -+ *str++ = (unsigned char)va_arg(args, int); -+ while (--field_width > 0) -+ *str++ = ' '; -+ continue; -+ -+ case 's': -+ s = va_arg(args, char *); -+ len = strnlen(s, precision); -+ -+ if (!(flags & LEFT)) -+ while (len < field_width--) -+ *str++ = ' '; -+ for (i = 0; i < len; ++i) -+ *str++ = *s++; -+ while (len < field_width--) -+ *str++ = ' '; -+ continue; -+ -+ case 'p': -+ if (field_width == -1) { -+ field_width = 2 * sizeof(void *); -+ flags |= ZEROPAD; -+ } -+ str = number(str, -+ (unsigned long)va_arg(args, void *), 16, -+ field_width, precision, flags); -+ continue; -+ -+ case 'n': -+ if (qualifier == 'l') { -+ long *ip = va_arg(args, long *); -+ *ip = (str - buf); -+ } else { -+ int *ip = va_arg(args, int *); -+ *ip = (str - buf); -+ } -+ continue; -+ -+ case '%': -+ *str++ = '%'; -+ continue; -+ -+ /* integer number formats - set up the flags and "break" */ -+ case 'o': -+ base = 8; -+ break; -+ -+ case 'X': -+ flags |= LARGE; -+ case 'x': -+ base = 16; -+ break; -+ -+ case 'd': -+ case 'i': -+ flags |= SIGN; -+ case 'u': -+ break; -+ -+ default: -+ *str++ = '%'; -+ if (*fmt) -+ *str++ = *fmt; -+ else -+ --fmt; -+ continue; -+ } -+ if (qualifier == 'l') -+ num = va_arg(args, unsigned long); -+ else if (qualifier == 'h') { -+ num = (unsigned short)va_arg(args, int); -+ if (flags & SIGN) -+ num = (short)num; -+ } else if (flags & SIGN) -+ num = va_arg(args, int); -+ else -+ num = va_arg(args, unsigned int); -+ str = number(str, num, base, field_width, precision, flags); -+ } -+ *str = '\0'; -+ return str - buf; -+} -+ -+int sprintf(char *buf, const char *fmt, ...) -+{ -+ va_list args; -+ int i; -+ -+ va_start(args, fmt); -+ i = vsprintf(buf, fmt, args); -+ va_end(args); -+ return i; -+} -+ -+int printf(const char *fmt, ...) -+{ -+ char printf_buf[1024]; -+ va_list args; -+ int printed; -+ -+ va_start(args, fmt); -+ printed = vsprintf(printf_buf, fmt, args); -+ va_end(args); -+ -+ puts(printf_buf); -+ -+ return printed; -+} ---- a/arch/i386/boot/setup.S -+++ /dev/null -@@ -1,1075 +0,0 @@ --/* -- * setup.S Copyright (C) 1991, 1992 Linus Torvalds -- * -- * setup.s is responsible for getting the system data from the BIOS, -- * and putting them into the appropriate places in system memory. -- * both setup.s and system has been loaded by the bootblock. -- * -- * This code asks the bios for memory/disk/other parameters, and -- * puts them in a "safe" place: 0x90000-0x901FF, ie where the -- * boot-block used to be. It is then up to the protected mode -- * system to read them from there before the area is overwritten -- * for buffer-blocks. -- * -- * Move PS/2 aux init code to psaux.c -- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 -- * -- * some changes and additional features by Christoph Niemann, -- * March 1993/June 1994 (Christoph.Niemann@linux.org) -- * -- * add APM BIOS checking by Stephen Rothwell, May 1994 -- * (sfr@canb.auug.org.au) -- * -- * High load stuff, initrd support and position independency -- * by Hans Lermen & Werner Almesberger, February 1996 -- * , -- * -- * Video handling moved to video.S by Martin Mares, March 1996 -- * -- * -- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david -- * parsons) to avoid loadlin confusion, July 1997 -- * -- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. -- * -- * -- * Fix to work around buggy BIOSes which don't use carry bit correctly -- * and/or report extended memory in CX/DX for e801h memory size detection -- * call. As a result the kernel got wrong figures. The int15/e801h docs -- * from Ralf Brown interrupt list seem to indicate AX/BX should be used -- * anyway. So to avoid breaking many machines (presumably there was a reason -- * to orginally use CX/DX instead of AX/BX), we do a kludge to see -- * if CX/DX have been changed in the e801 call and if so use AX/BX . -- * Michael Miller, April 2001 -- * -- * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes -- * by Robert Schwebel, December 2001 -- */ -- --#include --#include --#include --#include --#include --#include --#include -- --/* Signature words to ensure LILO loaded us right */ --#define SIG1 0xAA55 --#define SIG2 0x5A5A -- --INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way --SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). --SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment -- # ... and the former contents of CS -- --DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 -- --.code16 --.globl begtext, begdata, begbss, endtext, enddata, endbss -- --.text --begtext: --.data --begdata: --.bss --begbss: --.text -- --start: -- jmp trampoline -- --# This is the setup header, and it must start at %cs:2 (old 0x9020:2) -- -- .ascii "HdrS" # header signature -- .word 0x0206 # header version number (>= 0x0105) -- # or else old loadlin-1.5 will fail) --realmode_swtch: .word 0, 0 # default_switch, SETUPSEG --start_sys_seg: .word SYSSEG -- .word kernel_version # pointing to kernel version string -- # above section of header is compatible -- # with loadlin-1.5 (header v1.5). Don't -- # change it. -- --type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, -- # Bootlin, SYSLX, bootsect...) -- # See Documentation/i386/boot.txt for -- # assigned ids -- --# flags, unused bits must be zero (RFU) bit within loadflags --loadflags: --LOADED_HIGH = 1 # If set, the kernel is loaded high --CAN_USE_HEAP = 0x80 # If set, the loader also has set -- # heap_end_ptr to tell how much -- # space behind setup.S can be used for -- # heap purposes. -- # Only the loader knows what is free --#ifndef __BIG_KERNEL__ -- .byte 0 --#else -- .byte LOADED_HIGH --#endif -- --setup_move_size: .word 0x8000 # size to move, when setup is not -- # loaded at 0x90000. We will move setup -- # to 0x90000 then just before jumping -- # into the kernel. However, only the -- # loader knows how much data behind -- # us also needs to be loaded. -- --code32_start: # here loaders can put a different -- # start address for 32-bit code. --#ifndef __BIG_KERNEL__ -- .long 0x1000 # 0x1000 = default for zImage --#else -- .long 0x100000 # 0x100000 = default for big kernel --#endif -- --ramdisk_image: .long 0 # address of loaded ramdisk image -- # Here the loader puts the 32-bit -- # address where it loaded the image. -- # This only will be read by the kernel. -- --ramdisk_size: .long 0 # its size in bytes -- --bootsect_kludge: -- .long 0 # obsolete -- --heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) -- # space from here (exclusive) down to -- # end of setup code can be used by setup -- # for local heap purposes. -- --pad1: .word 0 --cmd_line_ptr: .long 0 # (Header version 0x0202 or later) -- # If nonzero, a 32-bit pointer -- # to the kernel command line. -- # The command line should be -- # located between the start of -- # setup and the end of low -- # memory (0xa0000), or it may -- # get overwritten before it -- # gets read. If this field is -- # used, there is no longer -- # anything magical about the -- # 0x90000 segment; the setup -- # can be located anywhere in -- # low memory 0x10000 or higher. -- --ramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff -- # (Header version 0x0203 or later) -- # The highest safe address for -- # the contents of an initrd -- --kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment -- #required for protected mode -- #kernel --#ifdef CONFIG_RELOCATABLE --relocatable_kernel: .byte 1 --#else --relocatable_kernel: .byte 0 --#endif --pad2: .byte 0 --pad3: .word 0 -- --cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, -- #added with boot protocol -- #version 2.06 -- --trampoline: call start_of_setup -- .align 16 -- # The offset at this point is 0x240 -- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) --# End of setup header ##################################################### -- --start_of_setup: --# Bootlin depends on this being done early -- movw $0x01500, %ax -- movb $0x81, %dl -- int $0x13 -- --#ifdef SAFE_RESET_DISK_CONTROLLER --# Reset the disk controller. -- movw $0x0000, %ax -- movb $0x80, %dl -- int $0x13 --#endif -- --# Set %ds = %cs, we know that SETUPSEG = %cs at this point -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds --# Check signature at end of setup -- cmpw $SIG1, setup_sig1 -- jne bad_sig -- -- cmpw $SIG2, setup_sig2 -- jne bad_sig -- -- jmp good_sig1 -- --# Routine to print asciiz string at ds:si --prtstr: -- lodsb -- andb %al, %al -- jz fin -- -- call prtchr -- jmp prtstr -- --fin: ret -- --# Space printing --prtsp2: call prtspc # Print double space --prtspc: movb $0x20, %al # Print single space (note: fall-thru) -- --# Part of above routine, this one just prints ascii al --prtchr: pushw %ax -- pushw %cx -- movw $7,%bx -- movw $0x01, %cx -- movb $0x0e, %ah -- int $0x10 -- popw %cx -- popw %ax -- ret -- --beep: movb $0x07, %al -- jmp prtchr -- --no_sig_mess: .string "No setup signature found ..." -- --good_sig1: -- jmp good_sig -- --# We now have to find the rest of the setup code/data --bad_sig: -- movw %cs, %ax # SETUPSEG -- subw $DELTA_INITSEG, %ax # INITSEG -- movw %ax, %ds -- xorb %bh, %bh -- movb (497), %bl # get setup sect from bootsect -- subw $4, %bx # LILO loads 4 sectors of setup -- shlw $8, %bx # convert to words (1sect=2^8 words) -- movw %bx, %cx -- shrw $3, %bx # convert to segment -- addw $SYSSEG, %bx -- movw %bx, %cs:start_sys_seg --# Move rest of setup code/data to here -- movw $2048, %di # four sectors loaded by LILO -- subw %si, %si -- pushw %cs -- popw %es -- movw $SYSSEG, %ax -- movw %ax, %ds -- rep -- movsw -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds -- cmpw $SIG1, setup_sig1 -- jne no_sig -- -- cmpw $SIG2, setup_sig2 -- jne no_sig -- -- jmp good_sig -- --no_sig: -- lea no_sig_mess, %si -- call prtstr -- --no_sig_loop: -- hlt -- jmp no_sig_loop -- --good_sig: -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %ds --# Check if an old loader tries to load a big-kernel -- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? -- jz loader_ok # No, no danger for old loaders. -- -- cmpb $0, %cs:type_of_loader # Do we have a loader that -- # can deal with us? -- jnz loader_ok # Yes, continue. -- -- pushw %cs # No, we have an old loader, -- popw %ds # die. -- lea loader_panic_mess, %si -- call prtstr -- -- jmp no_sig_loop -- --loader_panic_mess: .string "Wrong loader, giving up..." -- --# check minimum cpuid --# we do this here because it is the last place we can actually --# show a user visible error message. Later the video modus --# might be already messed up. --loader_ok: -- call verify_cpu -- testl %eax,%eax -- jz cpu_ok -- movw %cs,%ax # aka SETUPSEG -- movw %ax,%ds -- lea cpu_panic_mess,%si -- call prtstr --1: jmp 1b -- --cpu_panic_mess: -- .asciz "PANIC: CPU too old for this kernel." -- --#include "../kernel/verify_cpu.S" -- --cpu_ok: --# Get memory size (extended mem, kB) -- -- xorl %eax, %eax -- movl %eax, (0x1e0) --#ifndef STANDARD_MEMORY_BIOS_CALL -- movb %al, (E820NR) --# Try three different memory detection schemes. First, try --# e820h, which lets us assemble a memory map, then try e801h, --# which returns a 32-bit memory size, and finally 88h, which --# returns 0-64m -- --# method E820H: --# the memory map from hell. e820h returns memory classified into --# a whole bunch of different types, and allows memory holes and --# everything. We scan through this memory map and build a list --# of the first 32 memory areas, which we return at [E820MAP]. --# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. -- --#define SMAP 0x534d4150 -- --meme820: -- xorl %ebx, %ebx # continuation counter -- movw $E820MAP, %di # point into the whitelist -- # so we can have the bios -- # directly write into it. -- --jmpe820: -- movl $0x0000e820, %eax # e820, upper word zeroed -- movl $SMAP, %edx # ascii 'SMAP' -- movl $20, %ecx # size of the e820rec -- pushw %ds # data record. -- popw %es -- int $0x15 # make the call -- jc bail820 # fall to e801 if it fails -- -- cmpl $SMAP, %eax # check the return is `SMAP' -- jne bail820 # fall to e801 if it fails -- --# cmpl $1, 16(%di) # is this usable memory? --# jne again820 -- -- # If this is usable memory, we save it by simply advancing %di by -- # sizeof(e820rec). -- # --good820: -- movb (E820NR), %al # up to 128 entries -- cmpb $E820MAX, %al -- jae bail820 -- -- incb (E820NR) -- movw %di, %ax -- addw $20, %ax -- movw %ax, %di --again820: -- cmpl $0, %ebx # check to see if -- jne jmpe820 # %ebx is set to EOF --bail820: -- -- --# method E801H: --# memory size is in 1k chunksizes, to avoid confusing loadlin. --# we store the 0xe801 memory size in a completely different place, --# because it will most likely be longer than 16 bits. --# (use 1e0 because that's what Larry Augustine uses in his --# alternative new memory detection scheme, and it's sensible --# to write everything into the same place.) -- --meme801: -- stc # fix to work around buggy -- xorw %cx,%cx # BIOSes which don't clear/set -- xorw %dx,%dx # carry on pass/error of -- # e801h memory size call -- # or merely pass cx,dx though -- # without changing them. -- movw $0xe801, %ax -- int $0x15 -- jc mem88 -- -- cmpw $0x0, %cx # Kludge to handle BIOSes -- jne e801usecxdx # which report their extended -- cmpw $0x0, %dx # memory in AX/BX rather than -- jne e801usecxdx # CX/DX. The spec I have read -- movw %ax, %cx # seems to indicate AX/BX -- movw %bx, %dx # are more reasonable anyway... -- --e801usecxdx: -- andl $0xffff, %edx # clear sign extend -- shll $6, %edx # and go from 64k to 1k chunks -- movl %edx, (0x1e0) # store extended memory size -- andl $0xffff, %ecx # clear sign extend -- addl %ecx, (0x1e0) # and add lower memory into -- # total size. -- --# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or --# 64mb, depending on the bios) in ax. --mem88: -- --#endif -- movb $0x88, %ah -- int $0x15 -- movw %ax, (2) -- --# Set the keyboard repeat rate to the max -- movw $0x0305, %ax -- xorw %bx, %bx -- int $0x16 -- --# Check for video adapter and its parameters and allow the --# user to browse video modes. -- call video # NOTE: we need %ds pointing -- # to bootsector -- --# Get hd0 data... -- xorw %ax, %ax -- movw %ax, %ds -- ldsw (4 * 0x41), %si -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- pushw %ax -- movw %ax, %es -- movw $0x0080, %di -- movw $0x10, %cx -- pushw %cx -- cld -- rep -- movsb --# Get hd1 data... -- xorw %ax, %ax -- movw %ax, %ds -- ldsw (4 * 0x46), %si -- popw %cx -- popw %es -- movw $0x0090, %di -- rep -- movsb --# Check that there IS a hd1 :-) -- movw $0x01500, %ax -- movb $0x81, %dl -- int $0x13 -- jc no_disk1 -- -- cmpb $3, %ah -- je is_disk1 -- --no_disk1: -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %es -- movw $0x0090, %di -- movw $0x10, %cx -- xorw %ax, %ax -- cld -- rep -- stosb --is_disk1: --# check for Micro Channel (MCA) bus -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %ds -- xorw %ax, %ax -- movw %ax, (0xa0) # set table length to 0 -- movb $0xc0, %ah -- stc -- int $0x15 # moves feature table to es:bx -- jc no_mca -- -- pushw %ds -- movw %es, %ax -- movw %ax, %ds -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %es -- movw %bx, %si -- movw $0xa0, %di -- movw (%si), %cx -- addw $2, %cx # table length is a short -- cmpw $0x10, %cx -- jc sysdesc_ok -- -- movw $0x10, %cx # we keep only first 16 bytes --sysdesc_ok: -- rep -- movsb -- popw %ds --no_mca: --#ifdef CONFIG_X86_VOYAGER -- movb $0xff, 0x40 # flag on config found -- movb $0xc0, %al -- mov $0xff, %ah -- int $0x15 # put voyager config info at es:di -- jc no_voyager -- movw $0x40, %si # place voyager info in apm table -- cld -- movw $7, %cx --voyager_rep: -- movb %es:(%di), %al -- movb %al,(%si) -- incw %di -- incw %si -- decw %cx -- jnz voyager_rep --no_voyager: --#endif --# Check for PS/2 pointing device -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %ds -- movb $0, (0x1ff) # default is no pointing device -- int $0x11 # int 0x11: equipment list -- testb $0x04, %al # check if mouse installed -- jz no_psmouse -- -- movb $0xAA, (0x1ff) # device present --no_psmouse: -- --#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) -- movl $0x0000E980, %eax # IST Support -- movl $0x47534943, %edx # Request value -- int $0x15 -- -- movl %eax, (96) -- movl %ebx, (100) -- movl %ecx, (104) -- movl %edx, (108) --#endif -- --#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) --# Then check for an APM BIOS... -- # %ds points to the bootsector -- movw $0, 0x40 # version = 0 means no APM BIOS -- movw $0x05300, %ax # APM BIOS installation check -- xorw %bx, %bx -- int $0x15 -- jc done_apm_bios # Nope, no APM BIOS -- -- cmpw $0x0504d, %bx # Check for "PM" signature -- jne done_apm_bios # No signature, no APM BIOS -- -- andw $0x02, %cx # Is 32 bit supported? -- je done_apm_bios # No 32-bit, no (good) APM BIOS -- -- movw $0x05304, %ax # Disconnect first just in case -- xorw %bx, %bx -- int $0x15 # ignore return code -- movw $0x05303, %ax # 32 bit connect -- xorl %ebx, %ebx -- xorw %cx, %cx # paranoia :-) -- xorw %dx, %dx # ... -- xorl %esi, %esi # ... -- xorw %di, %di # ... -- int $0x15 -- jc no_32_apm_bios # Ack, error. -- -- movw %ax, (66) # BIOS code segment -- movl %ebx, (68) # BIOS entry point offset -- movw %cx, (72) # BIOS 16 bit code segment -- movw %dx, (74) # BIOS data segment -- movl %esi, (78) # BIOS code segment lengths -- movw %di, (82) # BIOS data segment length --# Redo the installation check as the 32 bit connect --# modifies the flags returned on some BIOSs -- movw $0x05300, %ax # APM BIOS installation check -- xorw %bx, %bx -- xorw %cx, %cx # paranoia -- int $0x15 -- jc apm_disconnect # error -> shouldn't happen -- -- cmpw $0x0504d, %bx # check for "PM" signature -- jne apm_disconnect # no sig -> shouldn't happen -- -- movw %ax, (64) # record the APM BIOS version -- movw %cx, (76) # and flags -- jmp done_apm_bios -- --apm_disconnect: # Tidy up -- movw $0x05304, %ax # Disconnect -- xorw %bx, %bx -- int $0x15 # ignore return code -- -- jmp done_apm_bios -- --no_32_apm_bios: -- andw $0xfffd, (76) # remove 32 bit support bit --done_apm_bios: --#endif -- --#include "edd.S" -- --# Now we want to move to protected mode ... -- cmpw $0, %cs:realmode_swtch -- jz rmodeswtch_normal -- -- lcall *%cs:realmode_swtch -- -- jmp rmodeswtch_end -- --rmodeswtch_normal: -- pushw %cs -- call default_switch -- --rmodeswtch_end: --# Now we move the system to its rightful place ... but we check if we have a --# big-kernel. In that case we *must* not move it ... -- testb $LOADED_HIGH, %cs:loadflags -- jz do_move0 # .. then we have a normal low -- # loaded zImage -- # .. or else we have a high -- # loaded bzImage -- jmp end_move # ... and we skip moving -- --do_move0: -- movw $0x100, %ax # start of destination segment -- movw %cs, %bp # aka SETUPSEG -- subw $DELTA_INITSEG, %bp # aka INITSEG -- movw %cs:start_sys_seg, %bx # start of source segment -- cld --do_move: -- movw %ax, %es # destination segment -- incb %ah # instead of add ax,#0x100 -- movw %bx, %ds # source segment -- addw $0x100, %bx -- subw %di, %di -- subw %si, %si -- movw $0x800, %cx -- rep -- movsw -- cmpw %bp, %bx # assume start_sys_seg > 0x200, -- # so we will perhaps read one -- # page more than needed, but -- # never overwrite INITSEG -- # because destination is a -- # minimum one page below source -- jb do_move -- --end_move: --# then we load the segment descriptors -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds -- --# Check whether we need to be downward compatible with version <=201 -- cmpl $0, cmd_line_ptr -- jne end_move_self # loader uses version >=202 features -- cmpb $0x20, type_of_loader -- je end_move_self # bootsect loader, we know of it -- --# Boot loader doesnt support boot protocol version 2.02. --# If we have our code not at 0x90000, we need to move it there now. --# We also then need to move the params behind it (commandline) --# Because we would overwrite the code on the current IP, we move --# it in two steps, jumping high after the first one. -- movw %cs, %ax -- cmpw $SETUPSEG, %ax -- je end_move_self -- -- cli # make sure we really have -- # interrupts disabled ! -- # because after this the stack -- # should not be used -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ss, %dx -- cmpw %ax, %dx -- jb move_self_1 -- -- addw $INITSEG, %dx -- subw %ax, %dx # this will go into %ss after -- # the move --move_self_1: -- movw %ax, %ds -- movw $INITSEG, %ax # real INITSEG -- movw %ax, %es -- movw %cs:setup_move_size, %cx -- std # we have to move up, so we use -- # direction down because the -- # areas may overlap -- movw %cx, %di -- decw %di -- movw %di, %si -- subw $move_self_here+0x200, %cx -- rep -- movsb -- ljmp $SETUPSEG, $move_self_here -- --move_self_here: -- movw $move_self_here+0x200, %cx -- rep -- movsb -- movw $SETUPSEG, %ax -- movw %ax, %ds -- movw %dx, %ss --end_move_self: # now we are at the right place -- --# --# Enable A20. This is at the very best an annoying procedure. --# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin. --# AMD Elan bug fix by Robert Schwebel. --# -- --#if defined(CONFIG_X86_ELAN) -- movb $0x02, %al # alternate A20 gate -- outb %al, $0x92 # this works on SC410/SC520 --a20_elan_wait: -- call a20_test -- jz a20_elan_wait -- jmp a20_done --#endif -- -- --A20_TEST_LOOPS = 32 # Iterations per wait --A20_ENABLE_LOOPS = 255 # Total loops to try -- -- --#ifndef CONFIG_X86_VOYAGER --a20_try_loop: -- -- # First, see if we are on a system with no A20 gate. --a20_none: -- call a20_test -- jnz a20_done -- -- # Next, try the BIOS (INT 0x15, AX=0x2401) --a20_bios: -- movw $0x2401, %ax -- pushfl # Be paranoid about flags -- int $0x15 -- popfl -- -- call a20_test -- jnz a20_done -- -- # Try enabling A20 through the keyboard controller --#endif /* CONFIG_X86_VOYAGER */ --a20_kbc: -- call empty_8042 -- --#ifndef CONFIG_X86_VOYAGER -- call a20_test # Just in case the BIOS worked -- jnz a20_done # but had a delayed reaction. --#endif -- -- movb $0xD1, %al # command write -- outb %al, $0x64 -- call empty_8042 -- -- movb $0xDF, %al # A20 on -- outb %al, $0x60 -- call empty_8042 -- --#ifndef CONFIG_X86_VOYAGER -- # Wait until a20 really *is* enabled; it can take a fair amount of -- # time on certain systems; Toshiba Tecras are known to have this -- # problem. --a20_kbc_wait: -- xorw %cx, %cx --a20_kbc_wait_loop: -- call a20_test -- jnz a20_done -- loop a20_kbc_wait_loop -- -- # Final attempt: use "configuration port A" --a20_fast: -- inb $0x92, %al # Configuration Port A -- orb $0x02, %al # "fast A20" version -- andb $0xFE, %al # don't accidentally reset -- outb %al, $0x92 -- -- # Wait for configuration port A to take effect --a20_fast_wait: -- xorw %cx, %cx --a20_fast_wait_loop: -- call a20_test -- jnz a20_done -- loop a20_fast_wait_loop -- -- # A20 is still not responding. Try frobbing it again. -- # -- decb (a20_tries) -- jnz a20_try_loop -- -- movw $a20_err_msg, %si -- call prtstr -- --a20_die: -- hlt -- jmp a20_die -- --a20_tries: -- .byte A20_ENABLE_LOOPS -- --a20_err_msg: -- .ascii "linux: fatal error: A20 gate not responding!" -- .byte 13, 10, 0 -- -- # If we get here, all is good --a20_done: -- --#endif /* CONFIG_X86_VOYAGER */ --# set up gdt and idt and 32bit start address -- lidt idt_48 # load idt with 0,0 -- xorl %eax, %eax # Compute gdt_base -- movw %ds, %ax # (Convert %ds:gdt to a linear ptr) -- shll $4, %eax -- addl %eax, code32 -- addl $gdt, %eax -- movl %eax, (gdt_48+2) -- lgdt gdt_48 # load gdt with whatever is -- # appropriate -- --# make sure any possible coprocessor is properly reset.. -- xorw %ax, %ax -- outb %al, $0xf0 -- call delay -- -- outb %al, $0xf1 -- call delay -- --# well, that went ok, I hope. Now we mask all interrupts - the rest --# is done in init_IRQ(). -- movb $0xFF, %al # mask all interrupts for now -- outb %al, $0xA1 -- call delay -- -- movb $0xFB, %al # mask all irq's but irq2 which -- outb %al, $0x21 # is cascaded -- --# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't --# need no steenking BIOS anyway (except for the initial loading :-). --# The BIOS-routine wants lots of unnecessary data, and it's less --# "interesting" anyway. This is how REAL programmers do it. --# --# Well, now's the time to actually move into protected mode. To make --# things as simple as possible, we do no register set-up or anything, --# we let the gnu-compiled 32-bit programs do that. We just jump to --# absolute address 0x1000 (or the loader supplied one), --# in 32-bit protected mode. --# --# Note that the short jump isn't strictly needed, although there are --# reasons why it might be a good idea. It won't hurt in any case. -- movw $1, %ax # protected mode (PE) bit -- lmsw %ax # This is it! -- jmp flush_instr -- --flush_instr: -- xorw %bx, %bx # Flag to indicate a boot -- xorl %esi, %esi # Pointer to real-mode code -- movw %cs, %si -- subw $DELTA_INITSEG, %si -- shll $4, %esi # Convert to 32-bit pointer -- --# jump to startup_32 in arch/i386/boot/compressed/head.S --# --# NOTE: For high loaded big kernels we need a --# jmpi 0x100000,__BOOT_CS --# --# but we yet haven't reloaded the CS register, so the default size --# of the target offset still is 16 bit. --# However, using an operand prefix (0x66), the CPU will properly --# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference --# Manual, Mixing 16-bit and 32-bit code, page 16-6) -- -- .byte 0x66, 0xea # prefix + jmpi-opcode --code32: .long startup_32 # will be set to %cs+startup_32 -- .word __BOOT_CS --.code32 --startup_32: -- movl $(__BOOT_DS), %eax -- movl %eax, %ds -- movl %eax, %es -- movl %eax, %fs -- movl %eax, %gs -- movl %eax, %ss -- -- xorl %eax, %eax --1: incl %eax # check that A20 really IS enabled -- movl %eax, 0x00000000 # loop forever if it isn't -- cmpl %eax, 0x00100000 -- je 1b -- -- # Jump to the 32bit entry point -- jmpl *(code32_start - start + (DELTA_INITSEG << 4))(%esi) --.code16 -- --# Here's a bunch of information about your current kernel.. --kernel_version: .ascii UTS_RELEASE -- .ascii " (" -- .ascii LINUX_COMPILE_BY -- .ascii "@" -- .ascii LINUX_COMPILE_HOST -- .ascii ") " -- .ascii UTS_VERSION -- .byte 0 -- --# This is the default real mode switch routine. --# to be called just before protected mode transition --default_switch: -- cli # no interrupts allowed ! -- movb $0x80, %al # disable NMI for bootup -- # sequence -- outb %al, $0x70 -- lret -- -- --#ifndef CONFIG_X86_VOYAGER --# This routine tests whether or not A20 is enabled. If so, it --# exits with zf = 0. --# --# The memory address used, 0x200, is the int $0x80 vector, which --# should be safe. -- --A20_TEST_ADDR = 4*0x80 -- --a20_test: -- pushw %cx -- pushw %ax -- xorw %cx, %cx -- movw %cx, %fs # Low memory -- decw %cx -- movw %cx, %gs # High memory area -- movw $A20_TEST_LOOPS, %cx -- movw %fs:(A20_TEST_ADDR), %ax -- pushw %ax --a20_test_wait: -- incw %ax -- movw %ax, %fs:(A20_TEST_ADDR) -- call delay # Serialize and make delay constant -- cmpw %gs:(A20_TEST_ADDR+0x10), %ax -- loope a20_test_wait -- -- popw %fs:(A20_TEST_ADDR) -- popw %ax -- popw %cx -- ret -- --#endif /* CONFIG_X86_VOYAGER */ -- --# This routine checks that the keyboard command queue is empty --# (after emptying the output buffers) --# --# Some machines have delusions that the keyboard buffer is always full --# with no keyboard attached... --# --# If there is no keyboard controller, we will usually get 0xff --# to all the reads. With each IO taking a microsecond and --# a timeout of 100,000 iterations, this can take about half a --# second ("delay" == outb to port 0x80). That should be ok, --# and should also be plenty of time for a real keyboard controller --# to empty. --# -- --empty_8042: -- pushl %ecx -- movl $100000, %ecx -- --empty_8042_loop: -- decl %ecx -- jz empty_8042_end_loop -- -- call delay -- -- inb $0x64, %al # 8042 status port -- testb $1, %al # output buffer? -- jz no_output -- -- call delay -- inb $0x60, %al # read it -- jmp empty_8042_loop -- --no_output: -- testb $2, %al # is input buffer full? -- jnz empty_8042_loop # yes - loop --empty_8042_end_loop: -- popl %ecx -- ret -- --# Read the cmos clock. Return the seconds in al --gettime: -- pushw %cx -- movb $0x02, %ah -- int $0x1a -- movb %dh, %al # %dh contains the seconds -- andb $0x0f, %al -- movb %dh, %ah -- movb $0x04, %cl -- shrb %cl, %ah -- aad -- popw %cx -- ret -- --# Delay is needed after doing I/O --delay: -- outb %al,$0x80 -- ret -- --# Descriptor tables --# --# NOTE: The intel manual says gdt should be sixteen bytes aligned for --# efficiency reasons. However, there are machines which are known not --# to boot with misaligned GDTs, so alter this at your peril! If you alter --# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two --# empty GDT entries (one for NULL and one reserved). --# --# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is --# true for the Voyager Quad CPU card which will not boot without --# This directive. 16 byte aligment is recommended by intel. --# -- .align 16 --gdt: -- .fill GDT_ENTRY_BOOT_CS,8,0 -- -- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) -- .word 0 # base address = 0 -- .word 0x9A00 # code read/exec -- .word 0x00CF # granularity = 4096, 386 -- # (+5th nibble of limit) -- -- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) -- .word 0 # base address = 0 -- .word 0x9200 # data read/write -- .word 0x00CF # granularity = 4096, 386 -- # (+5th nibble of limit) --gdt_end: -- .align 4 -- -- .word 0 # alignment byte --idt_48: -- .word 0 # idt limit = 0 -- .word 0, 0 # idt base = 0L -- -- .word 0 # alignment byte --gdt_48: -- .word gdt_end - gdt - 1 # gdt limit -- .word 0, 0 # gdt base (filled in later) -- --# Include video setup & detection code -- --#include "video.S" -- --# Setup signature -- must be last --setup_sig1: .word SIG1 --setup_sig2: .word SIG2 -- --# After this point, there is some free space which is used by the video mode --# handling code to store the temporary mode table (not used by the kernel). -- --modelist: -- --.text --endtext: --.data --enddata: --.bss --endbss: ---- /dev/null -+++ b/arch/i386/boot/setup.ld -@@ -0,0 +1,54 @@ -+/* -+ * setup.ld -+ * -+ * Linker script for the i386 setup code -+ */ -+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -+OUTPUT_ARCH(i386) -+ENTRY(_start) -+ -+SECTIONS -+{ -+ . = 0; -+ .bstext : { *(.bstext) } -+ .bsdata : { *(.bsdata) } -+ -+ . = 497; -+ .header : { *(.header) } -+ .inittext : { *(.inittext) } -+ .initdata : { *(.initdata) } -+ .text : { *(.text*) } -+ -+ . = ALIGN(16); -+ .rodata : { *(.rodata*) } -+ -+ .videocards : { -+ video_cards = .; -+ *(.videocards) -+ video_cards_end = .; -+ } -+ -+ . = ALIGN(16); -+ .data : { *(.data*) } -+ -+ .signature : { -+ setup_sig = .; -+ LONG(0x5a5aaa55) -+ } -+ -+ -+ . = ALIGN(16); -+ .bss : -+ { -+ __bss_start = .; -+ *(.bss) -+ __bss_end = .; -+ } -+ . = ALIGN(16); -+ _end = .; -+ -+ /DISCARD/ : { *(.note*) } -+ -+ . = ASSERT(_end <= 0x8000, "Setup too big!"); -+ . = ASSERT(hdr == 0x1f1, "The setup header has the wrong offset!"); -+} ---- /dev/null -+++ b/arch/i386/boot/string.c -@@ -0,0 +1,34 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/string.c -+ * -+ * Very basic string functions -+ */ -+ -+#include "boot.h" -+#include -+ -+int strcmp(const char *str1, const char *str2) -+{ -+ const unsigned char *s1 = (const unsigned char *)str1; -+ const unsigned char *s2 = (const unsigned char *)str2; -+ int delta = 0; -+ -+ while (*s1 || *s2) { -+ delta = *s2 - *s1; -+ if (delta) -+ return delta; -+ s1++; -+ s2++; -+ } -+ return 0; -+} ---- a/arch/i386/boot/tools/build.c -+++ b/arch/i386/boot/tools/build.c -@@ -1,13 +1,12 @@ - /* - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1997 Martin Mares -+ * Copyright (C) 2007 H. Peter Anvin - */ - - /* - * This file builds a disk-image from three different files: - * -- * - bootsect: compatibility mbr which prints an error message if -- * someone tries to boot the kernel directly. - * - setup: 8086 machine code, sets up system parm - * - system: 80386 code for actual system - * -@@ -21,6 +20,7 @@ - * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 - * Cross compiling fixes by Gertjan van Wingerde, July 1996 - * Rewritten by Martin Mares, April 1997 -+ * Substantially overhauled by H. Peter Anvin, April 2007 - */ - - #include -@@ -32,23 +32,25 @@ - #include - #include - #include -+#include - #include - --typedef unsigned char byte; --typedef unsigned short word; --typedef unsigned long u32; -+typedef unsigned char u8; -+typedef unsigned short u16; -+typedef unsigned long u32; - - #define DEFAULT_MAJOR_ROOT 0 - #define DEFAULT_MINOR_ROOT 0 - --/* Minimal number of setup sectors (see also bootsect.S) */ --#define SETUP_SECTS 4 -+/* Minimal number of setup sectors */ -+#define SETUP_SECT_MIN 5 -+#define SETUP_SECT_MAX 64 - --byte buf[1024]; --int fd; -+/* This must be large enough to hold the entire setup */ -+u8 buf[SETUP_SECT_MAX*512]; - int is_big_kernel; - --void die(const char * str, ...) -+static void die(const char * str, ...) - { - va_list args; - va_start(args, str); -@@ -57,15 +59,9 @@ - exit(1); - } - --void file_open(const char *name) -+static void usage(void) - { -- if ((fd = open(name, O_RDONLY, 0)) < 0) -- die("Unable to open `%s': %m", name); --} -- --void usage(void) --{ -- die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); -+ die("Usage: build [-b] setup system [rootdev] [> image]"); - } - - int main(int argc, char ** argv) -@@ -73,27 +69,30 @@ - unsigned int i, sz, setup_sectors; - int c; - u32 sys_size; -- byte major_root, minor_root; -+ u8 major_root, minor_root; - struct stat sb; -+ FILE *file; -+ int fd; -+ void *kernel; - - if (argc > 2 && !strcmp(argv[1], "-b")) - { - is_big_kernel = 1; - argc--, argv++; - } -- if ((argc < 4) || (argc > 5)) -+ if ((argc < 3) || (argc > 4)) - usage(); -- if (argc > 4) { -- if (!strcmp(argv[4], "CURRENT")) { -+ if (argc > 3) { -+ if (!strcmp(argv[3], "CURRENT")) { - if (stat("/", &sb)) { - perror("/"); - die("Couldn't stat /"); - } - major_root = major(sb.st_dev); - minor_root = minor(sb.st_dev); -- } else if (strcmp(argv[4], "FLOPPY")) { -- if (stat(argv[4], &sb)) { -- perror(argv[4]); -+ } else if (strcmp(argv[3], "FLOPPY")) { -+ if (stat(argv[3], &sb)) { -+ perror(argv[3]); - die("Couldn't stat root device."); - } - major_root = major(sb.st_rdev); -@@ -108,79 +107,62 @@ - } - fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); - -- file_open(argv[1]); -- i = read(fd, buf, sizeof(buf)); -- fprintf(stderr,"Boot sector %d bytes.\n",i); -- if (i != 512) -- die("Boot block must be exactly 512 bytes"); -+ /* Copy the setup code */ -+ file = fopen(argv[1], "r"); -+ if (!file) -+ die("Unable to open `%s': %m", argv[1]); -+ c = fread(buf, 1, sizeof(buf), file); -+ if (ferror(file)) -+ die("read-error on `setup'"); -+ if (c < 1024) -+ die("The setup must be at least 1024 bytes"); - if (buf[510] != 0x55 || buf[511] != 0xaa) - die("Boot block hasn't got boot flag (0xAA55)"); -+ fclose(file); -+ -+ /* Pad unused space with zeros */ -+ setup_sectors = (c + 511) / 512; -+ if (setup_sectors < SETUP_SECT_MIN) -+ setup_sectors = SETUP_SECT_MIN; -+ i = setup_sectors*512; -+ memset(buf+c, 0, i-c); -+ -+ /* Set the default root device */ - buf[508] = minor_root; - buf[509] = major_root; -- if (write(1, buf, 512) != 512) -- die("Write call failed"); -- close (fd); -- -- file_open(argv[2]); /* Copy the setup code */ -- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) -- if (write(1, buf, c) != c) -- die("Write call failed"); -- if (c != 0) -- die("read-error on `setup'"); -- close (fd); - -- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ -- /* for compatibility with ancient versions of LILO. */ -- if (setup_sectors < SETUP_SECTS) -- setup_sectors = SETUP_SECTS; -- fprintf(stderr, "Setup is %d bytes.\n", i); -- memset(buf, 0, sizeof(buf)); -- while (i < setup_sectors * 512) { -- c = setup_sectors * 512 - i; -- if (c > sizeof(buf)) -- c = sizeof(buf); -- if (write(1, buf, c) != c) -- die("Write call failed"); -- i += c; -- } -+ fprintf(stderr, "Setup is %d bytes (padded to %d bytes).\n", c, i); - -- file_open(argv[3]); -- if (fstat (fd, &sb)) -- die("Unable to stat `%s': %m", argv[3]); -+ /* Open and stat the kernel file */ -+ fd = open(argv[2], O_RDONLY); -+ if (fd < 0) -+ die("Unable to open `%s': %m", argv[2]); -+ if (fstat(fd, &sb)) -+ die("Unable to stat `%s': %m", argv[2]); - sz = sb.st_size; -- fprintf (stderr, "System is %d kB\n", sz/1024); -+ fprintf (stderr, "System is %d kB\n", (sz+1023)/1024); -+ kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); -+ if (kernel == MAP_FAILED) -+ die("Unable to mmap '%s': %m", argv[2]); - sys_size = (sz + 15) / 16; - if (!is_big_kernel && sys_size > DEF_SYSSIZE) - die("System is too big. Try using bzImage or modules."); -- while (sz > 0) { -- int l, n; - -- l = (sz > sizeof(buf)) ? sizeof(buf) : sz; -- if ((n=read(fd, buf, l)) != l) { -- if (n < 0) -- die("Error reading %s: %m", argv[3]); -- else -- die("%s: Unexpected EOF", argv[3]); -- } -- if (write(1, buf, l) != l) -- die("Write failed"); -- sz -= l; -- } -+ /* Patch the setup code with the appropriate size parameters */ -+ buf[0x1f1] = setup_sectors-1; -+ buf[0x1f4] = sys_size; -+ buf[0x1f5] = sys_size >> 8; -+ buf[0x1f6] = sys_size >> 16; -+ buf[0x1f7] = sys_size >> 24; -+ -+ if (fwrite(buf, 1, i, stdout) != i) -+ die("Writing setup failed"); -+ -+ /* Copy the kernel code */ -+ if (fwrite(kernel, 1, sz, stdout) != sz) -+ die("Writing kernel failed"); - close(fd); - -- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ -- die("Output: seek failed"); -- buf[0] = setup_sectors; -- if (write(1, buf, 1) != 1) -- die("Write of setup sector count failed"); -- if (lseek(1, 500, SEEK_SET) != 500) -- die("Output: seek failed"); -- buf[0] = (sys_size & 0xff); -- buf[1] = ((sys_size >> 8) & 0xff); -- buf[2] = ((sys_size >> 16) & 0xff); -- buf[3] = ((sys_size >> 24) & 0xff); -- if (write(1, buf, 4) != 4) -- die("Write of image length failed"); -- -- return 0; /* Everything is OK */ -+ /* Everything is OK */ -+ return 0; - } ---- /dev/null -+++ b/arch/i386/boot/tty.c -@@ -0,0 +1,112 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/tty.c -+ * -+ * Very simple screen I/O -+ * XXX: Probably should add very simple serial I/O? -+ */ -+ -+#include "boot.h" -+ -+/* -+ * These functions are in .inittext so they can be used to signal -+ * error during initialization. -+ */ -+ -+void __attribute__((section(".inittext"))) putchar(int ch) -+{ -+ unsigned char c = ch; -+ -+ if (c == '\n') -+ putchar('\r'); /* \n -> \r\n */ -+ -+ /* int $0x10 is known to have bugs involving touching registers -+ it shouldn't. Be extra conservative... */ -+ asm volatile("pushal; int $0x10; popal" -+ : : "b" (0x0007), "c" (0x0001), "a" (0x0e00|ch)); -+} -+ -+void __attribute__((section(".inittext"))) puts(const char *str) -+{ -+ int n = 0; -+ while (*str) { -+ putchar(*str++); -+ n++; -+ } -+} -+ -+/* -+ * Read the CMOS clock through the BIOS, and return the -+ * seconds in BCD. -+ */ -+ -+static u8 gettime(void) -+{ -+ u16 ax = 0x0200; -+ u16 cx, dx; -+ -+ asm("int $0x1a" -+ : "+a" (ax), "=c" (cx), "=d" (dx) -+ : : "ebx", "esi", "edi"); -+ -+ return dx >> 8; -+} -+ -+/* -+ * Read from the keyboard -+ */ -+int getchar(void) -+{ -+ u16 ax = 0; -+ asm("int $0x16" : "+a" (ax)); -+ -+ return ax & 0xff; -+} -+ -+static int kbd_pending(void) -+{ -+ u8 pending; -+ asm("int $0x16; setnz %0" -+ : "=rm" (pending) -+ : "a" (0x0100)); -+ return pending; -+} -+ -+void kbd_flush(void) -+{ -+ for (;;) { -+ if (!kbd_pending()) -+ break; -+ getchar(); -+ } -+} -+ -+int getchar_timeout(void) -+{ -+ int cnt = 30; -+ int t0, t1; -+ -+ t0 = gettime(); -+ -+ while (cnt) { -+ if (kbd_pending()) -+ return getchar(); -+ -+ t1 = gettime(); -+ if (t0 != t1) { -+ cnt--; -+ t0 = t1; -+ } -+ } -+ -+ return 0; /* Timeout! */ -+} ---- /dev/null -+++ b/arch/i386/boot/version.c -@@ -0,0 +1,23 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/version.c -+ * -+ * Kernel version string -+ */ -+ -+#include "boot.h" -+#include -+#include -+ -+const char kernel_version[] = -+ UTS_RELEASE " (" LINUX_COMPILE_BY "@" LINUX_COMPILE_HOST ") " -+ UTS_VERSION; ---- /dev/null -+++ b/arch/i386/boot/vesa.h -@@ -0,0 +1,79 @@ -+/* ----------------------------------------------------------------------- * -+ * -+ * Copyright 1999-2007 H. Peter Anvin - All Rights Reserved -+ * -+ * 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, Inc., 53 Temple Place Ste 330, -+ * Boston MA 02111-1307, USA; either version 2 of the License, or -+ * (at your option) any later version; incorporated herein by reference. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+#ifndef BOOT_VESA_H -+#define BOOT_VESA_H -+ -+typedef struct { -+ u16 off, seg; -+} far_ptr; -+ -+/* VESA General Information table */ -+struct vesa_general_info { -+ u32 signature; /* 0 Magic number = "VESA" */ -+ u16 version; /* 4 */ -+ far_ptr vendor_string; /* 6 */ -+ u32 capabilities; /* 10 */ -+ far_ptr video_mode_ptr; /* 14 */ -+ u16 total_memory; /* 18 */ -+ -+ u16 oem_software_rev; /* 20 */ -+ far_ptr oem_vendor_name_ptr; /* 22 */ -+ far_ptr oem_product_name_ptr; /* 26 */ -+ far_ptr oem_product_rev_ptr; /* 30 */ -+ -+ u8 reserved[222]; /* 34 */ -+ u8 oem_data[256]; /* 256 */ -+} __attribute__((packed)); -+ -+#define VESA_MAGIC ('V' + ('E' << 8) + ('S' << 16) + ('A' << 24)) -+#define VBE2_MAGIC ('V' + ('B' << 8) + ('E' << 16) + ('2' << 24)) -+ -+struct vesa_mode_info { -+ u16 mode_attr; /* 0 */ -+ u8 win_attr[2]; /* 2 */ -+ u16 win_grain; /* 4 */ -+ u16 win_size; /* 6 */ -+ u16 win_seg[2]; /* 8 */ -+ far_ptr win_scheme; /* 12 */ -+ u16 logical_scan; /* 16 */ -+ -+ u16 h_res; /* 18 */ -+ u16 v_res; /* 20 */ -+ u8 char_width; /* 22 */ -+ u8 char_height; /* 23 */ -+ u8 memory_planes; /* 24 */ -+ u8 bpp; /* 25 */ -+ u8 banks; /* 26 */ -+ u8 memory_layout; /* 27 */ -+ u8 bank_size; /* 28 */ -+ u8 image_planes; /* 29 */ -+ u8 page_function; /* 30 */ -+ -+ u8 rmask; /* 31 */ -+ u8 rpos; /* 32 */ -+ u8 gmask; /* 33 */ -+ u8 gpos; /* 34 */ -+ u8 bmask; /* 35 */ -+ u8 bpos; /* 36 */ -+ u8 resv_mask; /* 37 */ -+ u8 resv_pos; /* 38 */ -+ u8 dcm_info; /* 39 */ -+ -+ u32 lfb_ptr; /* 40 Linear frame buffer address */ -+ u32 offscreen_ptr; /* 44 Offscreen memory address */ -+ u16 offscreen_size; /* 48 */ -+ -+ u8 reserved[206]; /* 50 */ -+} __attribute__((packed)); -+ -+#endif /* LIB_SYS_VESA_H */ ---- /dev/null -+++ b/arch/i386/boot/video-bios.c -@@ -0,0 +1,125 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/video-bios.c -+ * -+ * Standard video BIOS modes -+ * -+ * We have two options for this; silent and scanned. -+ */ -+ -+#include "boot.h" -+#include "video.h" -+ -+__videocard video_bios; -+ -+/* Set a conventional BIOS mode */ -+static int set_bios_mode(u8 mode); -+ -+static int bios_set_mode(struct mode_info *mi) -+{ -+ return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS); -+} -+ -+static int set_bios_mode(u8 mode) -+{ -+ u16 ax; -+ u8 new_mode; -+ -+ ax = mode; /* AH=0x00 Set Video Mode */ -+ asm volatile(INT10 -+ : "+a" (ax) -+ : : "ebx", "ecx", "edx", "esi", "edi"); -+ -+ ax = 0x0f00; /* Get Current Video Mode */ -+ asm volatile(INT10 -+ : "+a" (ax) -+ : : "ebx", "ecx", "edx", "esi", "edi"); -+ -+ do_restore = 1; /* Assume video contents was lost */ -+ new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */ -+ -+ if (new_mode == mode) -+ return 0; /* Mode change OK */ -+ -+ if (new_mode != boot_params.screen_info.orig_video_mode) { -+ /* Mode setting failed, but we didn't end up where we -+ started. That's bad. Try to revert to the original -+ video mode. */ -+ ax = boot_params.screen_info.orig_video_mode; -+ asm volatile(INT10 -+ : "+a" (ax) -+ : : "ebx", "ecx", "edx", "esi", "edi"); -+ } -+ return -1; -+} -+ -+static int bios_probe(void) -+{ -+ u8 mode; -+ u8 saved_mode = boot_params.screen_info.orig_video_mode; -+ u16 crtc; -+ struct mode_info *mi; -+ int nmodes = 0; -+ -+ if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA) -+ return 0; -+ -+ set_fs(0); -+ crtc = vga_crtc(); -+ -+ video_bios.modes = GET_HEAP(struct mode_info, 0); -+ -+ for (mode = 0x14; mode <= 0x7f; mode++) { -+ if (heap_free() < sizeof(struct mode_info)) -+ break; -+ -+ if (mode_defined(VIDEO_FIRST_BIOS+mode)) -+ continue; -+ -+ if (set_bios_mode(mode)) -+ continue; -+ -+ /* Try to verify that it's a text mode. */ -+ -+ /* Attribute Controller: make graphics controller disabled */ -+ if (in_idx(0x3c0, 0x10) & 0x01) -+ continue; -+ -+ /* Graphics Controller: verify Alpha addressing enabled */ -+ if (in_idx(0x3ce, 0x06) & 0x01) -+ continue; -+ -+ /* CRTC cursor location low should be zero(?) */ -+ if (in_idx(crtc, 0x0f)) -+ continue; -+ -+ mi = GET_HEAP(struct mode_info, 1); -+ mi->mode = VIDEO_FIRST_BIOS+mode; -+ mi->x = rdfs16(0x44a); -+ mi->y = rdfs8(0x484)+1; -+ nmodes++; -+ } -+ -+ set_bios_mode(saved_mode); -+ -+ return nmodes; -+} -+ -+__videocard video_bios = -+{ -+ .card_name = "BIOS (scanned)", -+ .probe = bios_probe, -+ .set_mode = bios_set_mode, -+ .unsafe = 1, -+ .xmode_first = VIDEO_FIRST_BIOS, -+ .xmode_n = 0x80, -+}; ---- /dev/null -+++ b/arch/i386/boot/video-vesa.c -@@ -0,0 +1,283 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/video-vesa.c -+ * -+ * VESA text modes -+ */ -+ -+#include "boot.h" -+#include "video.h" -+#include "vesa.h" -+ -+/* VESA information */ -+static struct vesa_general_info vginfo; -+static struct vesa_mode_info vminfo; -+ -+__videocard video_vesa; -+ -+static void vesa_store_mode_params_graphics(void); -+ -+static int vesa_probe(void) -+{ -+#ifdef CONFIG_VIDEO_VESA -+ u16 ax; -+ u16 mode; -+ addr_t mode_ptr; -+ struct mode_info *mi; -+ int nmodes = 0; -+ -+ video_vesa.modes = GET_HEAP(struct mode_info, 0); -+ -+ vginfo.signature = VBE2_MAGIC; -+ -+ /* Optimistically assume a VESA BIOS is register-clean... */ -+ ax = 0x4f00; -+ asm("int $0x10" : "+a" (ax), "=m" (vginfo) : "D" (&vginfo)); -+ -+ if (ax != 0x004f || -+ vginfo.signature != VESA_MAGIC || -+ vginfo.version < 0x0102) -+ return 0; /* Not present */ -+ -+ set_fs(vginfo.video_mode_ptr.seg); -+ mode_ptr = vginfo.video_mode_ptr.off; -+ -+ while ((mode = rdfs16(mode_ptr)) != 0xffff) { -+ mode_ptr += 2; -+ -+ if (heap_free() < sizeof(struct mode_info)) -+ break; /* Heap full, can't save mode info */ -+ -+ if (mode & ~0x1ff) -+ continue; -+ -+ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ -+ -+ ax = 0x4f01; -+ asm("int $0x10" -+ : "+a" (ax), "=m" (vminfo) -+ : "c" (mode), "D" (&vminfo)); -+ -+ if (ax != 0x004f) -+ continue; -+ -+ if ((vminfo.mode_attr & 0x15) == 0x05) { -+ /* Text Mode, TTY BIOS supported, -+ supported by hardware */ -+ mi = GET_HEAP(struct mode_info, 1); -+ mi->mode = mode + VIDEO_FIRST_VESA; -+ mi->x = vminfo.h_res; -+ mi->y = vminfo.v_res; -+ nmodes++; -+ } else if ((vminfo.mode_attr & 0x99) == 0x99) { -+#ifdef CONFIG_FB -+ /* Graphics mode, color, linear frame buffer -+ supported -- register the mode but hide from -+ the menu. Only do this if framebuffer is -+ configured, however, otherwise the user will -+ be left without a screen. */ -+ mi = GET_HEAP(struct mode_info, 1); -+ mi->mode = mode + VIDEO_FIRST_VESA; -+ mi->x = mi->y = 0; -+ nmodes++; -+#endif -+ } -+ } -+ -+ return nmodes; -+#else -+ return 0; -+#endif -+} -+ -+static int vesa_set_mode(struct mode_info *mode) -+{ -+ u16 ax; -+ int is_graphic; -+ u16 vesa_mode = mode->mode - VIDEO_FIRST_VESA; -+ -+ memset(&vminfo, 0, sizeof vminfo); /* Just in case... */ -+ -+ ax = 0x4f01; -+ asm("int $0x10" -+ : "+a" (ax), "=m" (vminfo) -+ : "c" (vesa_mode), "D" (&vminfo)); -+ -+ if (ax != 0x004f) -+ return -1; -+ -+ if ((vminfo.mode_attr & 0x15) == 0x05) { -+ /* It's a supported text mode */ -+ is_graphic = 0; -+ } else if ((vminfo.mode_attr & 0x99) == 0x99) { -+ /* It's a graphics mode with linear frame buffer */ -+ is_graphic = 1; -+ vesa_mode |= 0x4000; /* Request linear frame buffer */ -+ } else { -+ return -1; /* Invalid mode */ -+ } -+ -+ -+ ax = 0x4f02; -+ asm volatile("int $0x10" -+ : "+a" (ax) -+ : "b" (vesa_mode), "D" (0)); -+ -+ if (ax != 0x004f) -+ return -1; -+ -+ graphic_mode = is_graphic; -+ if (!is_graphic) { -+ /* Text mode */ -+ force_x = mode->x; -+ force_y = mode->y; -+ do_restore = 1; -+ } else { -+ /* Graphics mode */ -+ vesa_store_mode_params_graphics(); -+ } -+ -+ return 0; -+} -+ -+ -+/* Switch DAC to 8-bit mode */ -+static void vesa_dac_set_8bits(void) -+{ -+ u8 dac_size = 6; -+ -+ /* If possible, switch the DAC to 8-bit mode */ -+ if (vginfo.capabilities & 1) { -+ u16 ax, bx; -+ -+ ax = 0x4f08; -+ bx = 0x0800; -+ asm volatile(INT10 -+ : "+a" (ax), "+b" (bx) -+ : : "ecx", "edx", "esi", "edi"); -+ -+ if (ax == 0x004f) -+ dac_size = bx >> 8; -+ } -+ -+ /* Set the color sizes to the DAC size, and offsets to 0 */ -+ boot_params.screen_info.red_size = dac_size; -+ boot_params.screen_info.green_size = dac_size; -+ boot_params.screen_info.blue_size = dac_size; -+ boot_params.screen_info.rsvd_size = dac_size; -+ -+ boot_params.screen_info.red_pos = 0; -+ boot_params.screen_info.green_pos = 0; -+ boot_params.screen_info.blue_pos = 0; -+ boot_params.screen_info.rsvd_pos = 0; -+} -+ -+/* Save the VESA protected mode info */ -+static void vesa_store_pm_info(void) -+{ -+ u16 ax, bx, di, es; -+ -+ ax = 0x4f0a; -+ bx = di = 0; -+ asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es" -+ : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di) -+ : : "ecx", "esi"); -+ -+ if (ax != 0x004f) -+ return; -+ -+ boot_params.screen_info.vesapm_seg = es; -+ boot_params.screen_info.vesapm_off = di; -+} -+ -+/* -+ * Save video mode parameters for graphics mode -+ */ -+static void vesa_store_mode_params_graphics(void) -+{ -+ /* Tell the kernel we're in VESA graphics mode */ -+ boot_params.screen_info.orig_video_isVGA = 0x23; -+ -+ /* Mode parameters */ -+ boot_params.screen_info.vesa_attributes = vminfo.mode_attr; -+ boot_params.screen_info.lfb_linelength = vminfo.logical_scan; -+ boot_params.screen_info.lfb_width = vminfo.h_res; -+ boot_params.screen_info.lfb_height = vminfo.v_res; -+ boot_params.screen_info.lfb_depth = vminfo.bpp; -+ boot_params.screen_info.pages = vminfo.image_planes; -+ boot_params.screen_info.lfb_base = vminfo.lfb_ptr; -+ memcpy(&boot_params.screen_info.red_size, -+ &vminfo.rmask, 8); -+ -+ /* General parameters */ -+ boot_params.screen_info.lfb_size = vginfo.total_memory; -+ -+ if (vminfo.bpp <= 8) -+ vesa_dac_set_8bits(); -+ -+ vesa_store_pm_info(); -+} -+ -+/* -+ * Save EDID information for the kernel; this is invoked, separately, -+ * after mode-setting. -+ */ -+void vesa_store_edid(void) -+{ -+#ifdef CONFIG_FIRMWARE_EDID -+ u16 ax, bx, cx, dx, di; -+ -+ /* Apparently used as a nonsense token... */ -+ memset(&boot_params.edid_info, 0x13, sizeof boot_params.edid_info); -+ -+ if (vginfo.version < 0x0200) -+ return; /* EDID requires VBE 2.0+ */ -+ -+ ax = 0x4f15; /* VBE DDC */ -+ bx = 0x0000; /* Report DDC capabilities */ -+ cx = 0; /* Controller 0 */ -+ di = 0; /* ES:DI must be 0 by spec */ -+ -+ /* Note: The VBE DDC spec is different from the main VESA spec; -+ we genuinely have to assume all registers are destroyed here. */ -+ -+ asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" -+ : "+a" (ax), "+b" (bx) -+ : "c" (cx), "D" (di) -+ : "esi"); -+ -+ if (ax != 0x004f) -+ return; /* No EDID */ -+ -+ /* BH = time in seconds to transfer EDD information */ -+ /* BL = DDC level supported */ -+ -+ ax = 0x4f15; /* VBE DDC */ -+ bx = 0x0001; /* Read EDID */ -+ cx = 0; /* Controller 0 */ -+ dx = 0; /* EDID block number */ -+ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ -+ asm(INT10 -+ : "+a" (ax), "+b" (bx), "+d" (dx) -+ : "c" (cx), "D" (di) -+ : "esi"); -+#endif /* CONFIG_FIRMWARE_EDID */ -+} -+ -+__videocard video_vesa = -+{ -+ .card_name = "VESA", -+ .probe = vesa_probe, -+ .set_mode = vesa_set_mode, -+ .xmode_first = VIDEO_FIRST_VESA, -+ .xmode_n = 0x200, -+}; ---- /dev/null -+++ b/arch/i386/boot/video-vga.c -@@ -0,0 +1,260 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/video-vga.c -+ * -+ * Common all-VGA modes -+ */ -+ -+#include "boot.h" -+#include "video.h" -+ -+static struct mode_info vga_modes[] = { -+ { VIDEO_80x25, 80, 25 }, -+ { VIDEO_8POINT, 80, 50 }, -+ { VIDEO_80x43, 80, 43 }, -+ { VIDEO_80x28, 80, 28 }, -+ { VIDEO_80x30, 80, 30 }, -+ { VIDEO_80x34, 80, 34 }, -+ { VIDEO_80x60, 80, 60 }, -+}; -+ -+static struct mode_info ega_modes[] = { -+ { VIDEO_80x25, 80, 25 }, -+ { VIDEO_8POINT, 80, 43 }, -+}; -+ -+static struct mode_info cga_modes[] = { -+ { VIDEO_80x25, 80, 25 }, -+}; -+ -+__videocard video_vga; -+ -+/* Set basic 80x25 mode */ -+static u8 vga_set_basic_mode(void) -+{ -+ u16 ax; -+ u8 rows; -+ u8 mode; -+ -+#ifdef CONFIG_VIDEO_400_HACK -+ if (adapter >= ADAPTER_VGA) { -+ asm(INT10 -+ : : "a" (0x1202), "b" (0x0030) -+ : "ecx", "edx", "esi", "edi"); -+ } -+#endif -+ -+ ax = 0x0f00; -+ asm(INT10 -+ : "+a" (ax) -+ : : "ebx", "ecx", "edx", "esi", "edi"); -+ -+ mode = (u8)ax; -+ -+ set_fs(0); -+ rows = rdfs8(0x484); /* rows minus one */ -+ -+#ifndef CONFIG_VIDEO_400_HACK -+ if ((ax == 0x5003 || ax == 0x5007) && -+ (rows == 0 || rows == 24)) -+ return mode; -+#endif -+ -+ if (mode != 3 && mode != 7) -+ mode = 3; -+ -+ /* Set the mode */ -+ asm volatile(INT10 -+ : : "a" (mode) -+ : "ebx", "ecx", "edx", "esi", "edi"); -+ do_restore = 1; -+ return mode; -+} -+ -+static void vga_set_8font(void) -+{ -+ /* Set 8x8 font - 80x43 on EGA, 80x50 on VGA */ -+ -+ /* Set 8x8 font */ -+ asm volatile(INT10 : : "a" (0x1112), "b" (0)); -+ -+ /* Use alternate print screen */ -+ asm volatile(INT10 : : "a" (0x1200), "b" (0x20)); -+ -+ /* Turn off cursor emulation */ -+ asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); -+ -+ /* Cursor is scan lines 6-7 */ -+ asm volatile(INT10 : : "a" (0x0100), "c" (0x0607)); -+} -+ -+static void vga_set_14font(void) -+{ -+ /* Set 9x14 font - 80x28 on VGA */ -+ -+ /* Set 9x14 font */ -+ asm volatile(INT10 : : "a" (0x1111), "b" (0)); -+ -+ /* Turn off cursor emulation */ -+ asm volatile(INT10 : : "a" (0x1201), "b" (0x34)); -+ -+ /* Cursor is scan lines 11-12 */ -+ asm volatile(INT10 : : "a" (0x0100), "c" (0x0b0c)); -+} -+ -+static void vga_set_80x43(void) -+{ -+ /* Set 80x43 mode on VGA (not EGA) */ -+ -+ /* Set 350 scans */ -+ asm volatile(INT10 : : "a" (0x1201), "b" (0x30)); -+ -+ /* Reset video mode */ -+ asm volatile(INT10 : : "a" (0x0003)); -+ -+ vga_set_8font(); -+} -+ -+/* I/O address of the VGA CRTC */ -+u16 vga_crtc(void) -+{ -+ return (inb(0x3cc) & 1) ? 0x3d4 : 0x3b4; -+} -+ -+static void vga_set_480_scanlines(int end) -+{ -+ u16 crtc; -+ u8 csel; -+ -+ crtc = vga_crtc(); -+ -+ out_idx(0x0c, crtc, 0x11); /* Vertical sync end, unlock CR0-7 */ -+ out_idx(0x0b, crtc, 0x06); /* Vertical total */ -+ out_idx(0x3e, crtc, 0x07); /* Vertical overflow */ -+ out_idx(0xea, crtc, 0x10); /* Vertical sync start */ -+ out_idx(end, crtc, 0x12); /* Vertical display end */ -+ out_idx(0xe7, crtc, 0x15); /* Vertical blank start */ -+ out_idx(0x04, crtc, 0x16); /* Vertical blank end */ -+ csel = inb(0x3cc); -+ csel &= 0x0d; -+ csel |= 0xe2; -+ outb(csel, 0x3cc); -+} -+ -+static void vga_set_80x30(void) -+{ -+ vga_set_480_scanlines(0xdf); -+} -+ -+static void vga_set_80x34(void) -+{ -+ vga_set_14font(); -+ vga_set_480_scanlines(0xdb); -+} -+ -+static void vga_set_80x60(void) -+{ -+ vga_set_8font(); -+ vga_set_480_scanlines(0xdf); -+} -+ -+static int vga_set_mode(struct mode_info *mode) -+{ -+ /* Set the basic mode */ -+ vga_set_basic_mode(); -+ -+ /* Override a possibly broken BIOS */ -+ force_x = mode->x; -+ force_y = mode->y; -+ -+ switch (mode->mode) { -+ case VIDEO_80x25: -+ break; -+ case VIDEO_8POINT: -+ vga_set_8font(); -+ break; -+ case VIDEO_80x43: -+ vga_set_80x43(); -+ break; -+ case VIDEO_80x28: -+ vga_set_14font(); -+ break; -+ case VIDEO_80x30: -+ vga_set_80x30(); -+ break; -+ case VIDEO_80x34: -+ vga_set_80x34(); -+ break; -+ case VIDEO_80x60: -+ vga_set_80x60(); -+ break; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Note: this probe includes basic information required by all -+ * systems. It should be executed first, by making sure -+ * video-vga.c is listed first in the Makefile. -+ */ -+static int vga_probe(void) -+{ -+ static const char *card_name[] = { -+ "CGA/MDA/HGC", "EGA", "VGA" -+ }; -+ static struct mode_info *mode_lists[] = { -+ cga_modes, -+ ega_modes, -+ vga_modes, -+ }; -+ static int mode_count[] = { -+ sizeof(cga_modes)/sizeof(struct mode_info), -+ sizeof(ega_modes)/sizeof(struct mode_info), -+ sizeof(vga_modes)/sizeof(struct mode_info), -+ }; -+ u8 vga_flag; -+ -+ asm(INT10 -+ : "=b" (boot_params.screen_info.orig_video_ega_bx) -+ : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ -+ : "ecx", "edx", "esi", "edi"); -+ -+ /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ -+ if ((u8)boot_params.screen_info.orig_video_ega_bx != 0x10) { -+ /* EGA/VGA */ -+ asm(INT10 -+ : "=a" (vga_flag) -+ : "a" (0x1a00) -+ : "ebx", "ecx", "edx", "esi", "edi"); -+ -+ if (vga_flag == 0x1a) { -+ adapter = ADAPTER_VGA; -+ boot_params.screen_info.orig_video_isVGA = 1; -+ } else { -+ adapter = ADAPTER_EGA; -+ } -+ } else { -+ adapter = ADAPTER_CGA; -+ } -+ -+ video_vga.modes = mode_lists[adapter]; -+ video_vga.card_name = card_name[adapter]; -+ return mode_count[adapter]; -+} -+ -+__videocard video_vga = -+{ -+ .card_name = "VGA", -+ .probe = vga_probe, -+ .set_mode = vga_set_mode, -+}; ---- a/arch/i386/boot/video.S -+++ /dev/null -@@ -1,2043 +0,0 @@ --/* video.S -- * -- * Display adapter & video mode setup, version 2.13 (14-May-99) -- * -- * Copyright (C) 1995 -- 1998 Martin Mares -- * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson -- * -- * Rewritten to use GNU 'as' by Chris Noe May 1999 -- * -- * For further information, look at Documentation/svga.txt. -- * -- */ -- --/* Enable autodetection of SVGA adapters and modes. */ --#undef CONFIG_VIDEO_SVGA -- --/* Enable autodetection of VESA modes */ --#define CONFIG_VIDEO_VESA -- --/* Enable compacting of mode table */ --#define CONFIG_VIDEO_COMPACT -- --/* Retain screen contents when switching modes */ --#define CONFIG_VIDEO_RETAIN -- --/* Enable local mode list */ --#undef CONFIG_VIDEO_LOCAL -- --/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ --#undef CONFIG_VIDEO_400_HACK -- --/* Hack that lets you force specific BIOS mode ID and specific dimensions */ --#undef CONFIG_VIDEO_GFX_HACK --#define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */ --#define VIDEO_GFX_BIOS_BX 0x0102 --#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */ -- --/* This code uses an extended set of video mode numbers. These include: -- * Aliases for standard modes -- * NORMAL_VGA (-1) -- * EXTENDED_VGA (-2) -- * ASK_VGA (-3) -- * Video modes numbered by menu position -- NOT RECOMMENDED because of lack -- * of compatibility when extending the table. These are between 0x00 and 0xff. -- */ --#define VIDEO_FIRST_MENU 0x0000 -- --/* Standard BIOS video modes (BIOS number + 0x0100) */ --#define VIDEO_FIRST_BIOS 0x0100 -- --/* VESA BIOS video modes (VESA number + 0x0200) */ --#define VIDEO_FIRST_VESA 0x0200 -- --/* Video7 special modes (BIOS number + 0x0900) */ --#define VIDEO_FIRST_V7 0x0900 -- --/* Special video modes */ --#define VIDEO_FIRST_SPECIAL 0x0f00 --#define VIDEO_80x25 0x0f00 --#define VIDEO_8POINT 0x0f01 --#define VIDEO_80x43 0x0f02 --#define VIDEO_80x28 0x0f03 --#define VIDEO_CURRENT_MODE 0x0f04 --#define VIDEO_80x30 0x0f05 --#define VIDEO_80x34 0x0f06 --#define VIDEO_80x60 0x0f07 --#define VIDEO_GFX_HACK 0x0f08 --#define VIDEO_LAST_SPECIAL 0x0f09 -- --/* Video modes given by resolution */ --#define VIDEO_FIRST_RESOLUTION 0x1000 -- --/* The "recalculate timings" flag */ --#define VIDEO_RECALC 0x8000 -- --/* Positions of various video parameters passed to the kernel */ --/* (see also include/linux/tty.h) */ --#define PARAM_CURSOR_POS 0x00 --#define PARAM_VIDEO_PAGE 0x04 --#define PARAM_VIDEO_MODE 0x06 --#define PARAM_VIDEO_COLS 0x07 --#define PARAM_VIDEO_EGA_BX 0x0a --#define PARAM_VIDEO_LINES 0x0e --#define PARAM_HAVE_VGA 0x0f --#define PARAM_FONT_POINTS 0x10 -- --#define PARAM_LFB_WIDTH 0x12 --#define PARAM_LFB_HEIGHT 0x14 --#define PARAM_LFB_DEPTH 0x16 --#define PARAM_LFB_BASE 0x18 --#define PARAM_LFB_SIZE 0x1c --#define PARAM_LFB_LINELENGTH 0x24 --#define PARAM_LFB_COLORS 0x26 --#define PARAM_VESAPM_SEG 0x2e --#define PARAM_VESAPM_OFF 0x30 --#define PARAM_LFB_PAGES 0x32 --#define PARAM_VESA_ATTRIB 0x34 --#define PARAM_CAPABILITIES 0x36 -- --/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ --#ifdef CONFIG_VIDEO_RETAIN --#define DO_STORE call store_screen --#else --#define DO_STORE --#endif /* CONFIG_VIDEO_RETAIN */ -- --# This is the main entry point called by setup.S --# %ds *must* be pointing to the bootsector --video: pushw %ds # We use different segments -- pushw %ds # FS contains original DS -- popw %fs -- pushw %cs # DS is equal to CS -- popw %ds -- pushw %cs # ES is equal to CS -- popw %es -- xorw %ax, %ax -- movw %ax, %gs # GS is zero -- cld -- call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA) --#ifdef CONFIG_VIDEO_SELECT -- movw %fs:(0x01fa), %ax # User selected video mode -- cmpw $ASK_VGA, %ax # Bring up the menu -- jz vid2 -- -- call mode_set # Set the mode -- jc vid1 -- -- leaw badmdt, %si # Invalid mode ID -- call prtstr --vid2: call mode_menu --vid1: --#ifdef CONFIG_VIDEO_RETAIN -- call restore_screen # Restore screen contents --#endif /* CONFIG_VIDEO_RETAIN */ -- call store_edid --#endif /* CONFIG_VIDEO_SELECT */ -- call mode_params # Store mode parameters -- popw %ds # Restore original DS -- ret -- --# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel. --basic_detect: -- movb $0, %fs:(PARAM_HAVE_VGA) -- movb $0x12, %ah # Check EGA/VGA -- movb $0x10, %bl -- int $0x10 -- movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel -- cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card. -- je basret -- -- incb adapter -- movw $0x1a00, %ax # Check EGA or VGA? -- int $0x10 -- cmpb $0x1a, %al # 1a means VGA... -- jne basret # anything else is EGA. -- -- incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA -- incb adapter --basret: ret -- --# Store the video mode parameters for later usage by the kernel. --# This is done by asking the BIOS except for the rows/columns --# parameters in the default 80x25 mode -- these are set directly, --# because some very obscure BIOSes supply insane values. --mode_params: --#ifdef CONFIG_VIDEO_SELECT -- cmpb $0, graphic_mode -- jnz mopar_gr --#endif -- movb $0x03, %ah # Read cursor position -- xorb %bh, %bh -- int $0x10 -- movw %dx, %fs:(PARAM_CURSOR_POS) -- movb $0x0f, %ah # Read page/mode/width -- int $0x10 -- movw %bx, %fs:(PARAM_VIDEO_PAGE) -- movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width -- cmpb $0x7, %al # MDA/HGA => segment differs -- jnz mopar0 -- -- movw $0xb000, video_segment --mopar0: movw %gs:(0x485), %ax # Font size -- movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA) -- movw force_size, %ax # Forced size? -- orw %ax, %ax -- jz mopar1 -- -- movb %ah, %fs:(PARAM_VIDEO_COLS) -- movb %al, %fs:(PARAM_VIDEO_LINES) -- ret -- --mopar1: movb $25, %al -- cmpb $0, adapter # If we are on CGA/MDA/HGA, the -- jz mopar2 # screen must have 25 lines. -- -- movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS -- incb %al # location of max lines. --mopar2: movb %al, %fs:(PARAM_VIDEO_LINES) -- ret -- --#ifdef CONFIG_VIDEO_SELECT --# Fetching of VESA frame buffer parameters --mopar_gr: -- leaw modelist+1024, %di -- movb $0x23, %fs:(PARAM_HAVE_VGA) -- movw 16(%di), %ax -- movw %ax, %fs:(PARAM_LFB_LINELENGTH) -- movw 18(%di), %ax -- movw %ax, %fs:(PARAM_LFB_WIDTH) -- movw 20(%di), %ax -- movw %ax, %fs:(PARAM_LFB_HEIGHT) -- movb 25(%di), %al -- movb $0, %ah -- movw %ax, %fs:(PARAM_LFB_DEPTH) -- movb 29(%di), %al -- movb $0, %ah -- movw %ax, %fs:(PARAM_LFB_PAGES) -- movl 40(%di), %eax -- movl %eax, %fs:(PARAM_LFB_BASE) -- movl 31(%di), %eax -- movl %eax, %fs:(PARAM_LFB_COLORS) -- movl 35(%di), %eax -- movl %eax, %fs:(PARAM_LFB_COLORS+4) -- movw 0(%di), %ax -- movw %ax, %fs:(PARAM_VESA_ATTRIB) -- --# get video mem size -- leaw modelist+1024, %di -- movw $0x4f00, %ax -- int $0x10 -- xorl %eax, %eax -- movw 18(%di), %ax -- movl %eax, %fs:(PARAM_LFB_SIZE) -- --# store mode capabilities -- movl 10(%di), %eax -- movl %eax, %fs:(PARAM_CAPABILITIES) -- --# switching the DAC to 8-bit is for <= 8 bpp only -- movw %fs:(PARAM_LFB_DEPTH), %ax -- cmpw $8, %ax -- jg dac_done -- --# get DAC switching capability -- xorl %eax, %eax -- movb 10(%di), %al -- testb $1, %al -- jz dac_set -- --# attempt to switch DAC to 8-bit -- movw $0x4f08, %ax -- movw $0x0800, %bx -- int $0x10 -- cmpw $0x004f, %ax -- jne dac_set -- movb %bh, dac_size # store actual DAC size -- --dac_set: --# set color size to DAC size -- movb dac_size, %al -- movb %al, %fs:(PARAM_LFB_COLORS+0) -- movb %al, %fs:(PARAM_LFB_COLORS+2) -- movb %al, %fs:(PARAM_LFB_COLORS+4) -- movb %al, %fs:(PARAM_LFB_COLORS+6) -- --# set color offsets to 0 -- movb $0, %fs:(PARAM_LFB_COLORS+1) -- movb $0, %fs:(PARAM_LFB_COLORS+3) -- movb $0, %fs:(PARAM_LFB_COLORS+5) -- movb $0, %fs:(PARAM_LFB_COLORS+7) -- --dac_done: --# get protected mode interface informations -- movw $0x4f0a, %ax -- xorw %bx, %bx -- xorw %di, %di -- int $0x10 -- cmp $0x004f, %ax -- jnz no_pm -- -- movw %es, %fs:(PARAM_VESAPM_SEG) -- movw %di, %fs:(PARAM_VESAPM_OFF) --no_pm: ret -- --# The video mode menu --mode_menu: -- leaw keymsg, %si # "Return/Space/Timeout" message -- call prtstr -- call flush --nokey: call getkt -- -- cmpb $0x0d, %al # ENTER ? -- je listm # yes - manual mode selection -- -- cmpb $0x20, %al # SPACE ? -- je defmd1 # no - repeat -- -- call beep -- jmp nokey -- --defmd1: ret # No mode chosen? Default 80x25 -- --listm: call mode_table # List mode table --listm0: leaw name_bann, %si # Print adapter name -- call prtstr -- movw card_name, %si -- orw %si, %si -- jnz an2 -- -- movb adapter, %al -- leaw old_name, %si -- orb %al, %al -- jz an1 -- -- leaw ega_name, %si -- decb %al -- jz an1 -- -- leaw vga_name, %si -- jmp an1 -- --an2: call prtstr -- leaw svga_name, %si --an1: call prtstr -- leaw listhdr, %si # Table header -- call prtstr -- movb $0x30, %dl # DL holds mode number -- leaw modelist, %si --lm1: cmpw $ASK_VGA, (%si) # End? -- jz lm2 -- -- movb %dl, %al # Menu selection number -- call prtchr -- call prtsp2 -- lodsw -- call prthw # Mode ID -- call prtsp2 -- movb 0x1(%si), %al -- call prtdec # Rows -- movb $0x78, %al # the letter 'x' -- call prtchr -- lodsw -- call prtdec # Columns -- movb $0x0d, %al # New line -- call prtchr -- movb $0x0a, %al -- call prtchr -- incb %dl # Next character -- cmpb $0x3a, %dl -- jnz lm1 -- -- movb $0x61, %dl -- jmp lm1 -- --lm2: leaw prompt, %si # Mode prompt -- call prtstr -- leaw edit_buf, %di # Editor buffer --lm3: call getkey -- cmpb $0x0d, %al # Enter? -- jz lment -- -- cmpb $0x08, %al # Backspace? -- jz lmbs -- -- cmpb $0x20, %al # Printable? -- jc lm3 -- -- cmpw $edit_buf+4, %di # Enough space? -- jz lm3 -- -- stosb -- call prtchr -- jmp lm3 -- --lmbs: cmpw $edit_buf, %di # Backspace -- jz lm3 -- -- decw %di -- movb $0x08, %al -- call prtchr -- call prtspc -- movb $0x08, %al -- call prtchr -- jmp lm3 -- --lment: movb $0, (%di) -- leaw crlft, %si -- call prtstr -- leaw edit_buf, %si -- cmpb $0, (%si) # Empty string = default mode -- jz lmdef -- -- cmpb $0, 1(%si) # One character = menu selection -- jz mnusel -- -- cmpw $0x6373, (%si) # "scan" => mode scanning -- jnz lmhx -- -- cmpw $0x6e61, 2(%si) -- jz lmscan -- --lmhx: xorw %bx, %bx # Else => mode ID in hex --lmhex: lodsb -- orb %al, %al -- jz lmuse1 -- -- subb $0x30, %al -- jc lmbad -- -- cmpb $10, %al -- jc lmhx1 -- -- subb $7, %al -- andb $0xdf, %al -- cmpb $10, %al -- jc lmbad -- -- cmpb $16, %al -- jnc lmbad -- --lmhx1: shlw $4, %bx -- orb %al, %bl -- jmp lmhex -- --lmuse1: movw %bx, %ax -- jmp lmuse -- --mnusel: lodsb # Menu selection -- xorb %ah, %ah -- subb $0x30, %al -- jc lmbad -- -- cmpb $10, %al -- jc lmuse -- -- cmpb $0x61-0x30, %al -- jc lmbad -- -- subb $0x61-0x30-10, %al -- cmpb $36, %al -- jnc lmbad -- --lmuse: call mode_set -- jc lmdef -- --lmbad: leaw unknt, %si -- call prtstr -- jmp lm2 --lmscan: cmpb $0, adapter # Scanning only on EGA/VGA -- jz lmbad -- -- movw $0, mt_end # Scanning of modes is -- movb $1, scanning # done as new autodetection. -- call mode_table -- jmp listm0 --lmdef: ret -- --# Additional parts of mode_set... (relative jumps, you know) --setv7: # Video7 extended modes -- DO_STORE -- subb $VIDEO_FIRST_V7>>8, %bh -- movw $0x6f05, %ax -- int $0x10 -- stc -- ret -- --_setrec: jmp setrec # Ugly... --_set_80x25: jmp set_80x25 -- --# Aliases for backward compatibility. --setalias: -- movw $VIDEO_80x25, %ax -- incw %bx -- jz mode_set -- -- movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al -- incw %bx -- jnz setbad # Fall-through! -- --# Setting of user mode (AX=mode ID) => CF=success --mode_set: -- movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S -- movw %ax, %bx -- cmpb $0xff, %ah -- jz setalias -- -- testb $VIDEO_RECALC>>8, %ah -- jnz _setrec -- -- cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah -- jnc setres -- -- cmpb $VIDEO_FIRST_SPECIAL>>8, %ah -- jz setspc -- -- cmpb $VIDEO_FIRST_V7>>8, %ah -- jz setv7 -- -- cmpb $VIDEO_FIRST_VESA>>8, %ah -- jnc check_vesa -- -- orb %ah, %ah -- jz setmenu -- -- decb %ah -- jz setbios -- --setbad: clc -- movb $0, do_restore # The screen needn't be restored -- ret -- --setvesa: -- DO_STORE -- subb $VIDEO_FIRST_VESA>>8, %bh -- movw $0x4f02, %ax # VESA BIOS mode set call -- int $0x10 -- cmpw $0x004f, %ax # AL=4f if implemented -- jnz setbad # AH=0 if OK -- -- stc -- ret -- --setbios: -- DO_STORE -- int $0x10 # Standard BIOS mode set call -- pushw %bx -- movb $0x0f, %ah # Check if really set -- int $0x10 -- popw %bx -- cmpb %bl, %al -- jnz setbad -- -- stc -- ret -- --setspc: xorb %bh, %bh # Set special mode -- cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl -- jnc setbad -- -- addw %bx, %bx -- jmp *spec_inits(%bx) -- --setmenu: -- orb %al, %al # 80x25 is an exception -- jz _set_80x25 -- -- pushw %bx # Set mode chosen from menu -- call mode_table # Build the mode table -- popw %ax -- shlw $2, %ax -- addw %ax, %si -- cmpw %di, %si -- jnc setbad -- -- movw (%si), %ax # Fetch mode ID --_m_s: jmp mode_set -- --setres: pushw %bx # Set mode chosen by resolution -- call mode_table -- popw %bx -- xchgb %bl, %bh --setr1: lodsw -- cmpw $ASK_VGA, %ax # End of the list? -- jz setbad -- -- lodsw -- cmpw %bx, %ax -- jnz setr1 -- -- movw -4(%si), %ax # Fetch mode ID -- jmp _m_s -- --check_vesa: --#ifdef CONFIG_FIRMWARE_EDID -- leaw modelist+1024, %di -- movw $0x4f00, %ax -- int $0x10 -- cmpw $0x004f, %ax -- jnz setbad -- -- movw 4(%di), %ax -- movw %ax, vbe_version --#endif -- leaw modelist+1024, %di -- subb $VIDEO_FIRST_VESA>>8, %bh -- movw %bx, %cx # Get mode information structure -- movw $0x4f01, %ax -- int $0x10 -- addb $VIDEO_FIRST_VESA>>8, %bh -- cmpw $0x004f, %ax -- jnz setbad -- -- movb (%di), %al # Check capabilities. -- andb $0x19, %al -- cmpb $0x09, %al -- jz setvesa # This is a text mode -- -- movb (%di), %al # Check capabilities. -- andb $0x99, %al -- cmpb $0x99, %al -- jnz _setbad # Doh! No linear frame buffer. -- -- subb $VIDEO_FIRST_VESA>>8, %bh -- orw $0x4000, %bx # Use linear frame buffer -- movw $0x4f02, %ax # VESA BIOS mode set call -- int $0x10 -- cmpw $0x004f, %ax # AL=4f if implemented -- jnz _setbad # AH=0 if OK -- -- movb $1, graphic_mode # flag graphic mode -- movb $0, do_restore # no screen restore -- stc -- ret -- --_setbad: jmp setbad # Ugly... -- --# Recalculate vertical display end registers -- this fixes various --# inconsistencies of extended modes on many adapters. Called when --# the VIDEO_RECALC flag is set in the mode ID. -- --setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode -- call mode_set -- jnc rct3 -- -- movw %gs:(0x485), %ax # Font size in pixels -- movb %gs:(0x484), %bl # Number of rows -- incb %bl -- mulb %bl # Number of visible -- decw %ax # scan lines - 1 -- movw $0x3d4, %dx -- movw %ax, %bx -- movb $0x12, %al # Lower 8 bits -- movb %bl, %ah -- outw %ax, %dx -- movb $0x07, %al # Bits 8 and 9 in the overflow register -- call inidx -- xchgb %al, %ah -- andb $0xbd, %ah -- shrb %bh -- jnc rct1 -- orb $0x02, %ah --rct1: shrb %bh -- jnc rct2 -- orb $0x40, %ah --rct2: movb $0x07, %al -- outw %ax, %dx -- stc --rct3: ret -- --# Table of routines for setting of the special modes. --spec_inits: -- .word set_80x25 -- .word set_8pixel -- .word set_80x43 -- .word set_80x28 -- .word set_current -- .word set_80x30 -- .word set_80x34 -- .word set_80x60 -- .word set_gfx -- --# Set the 80x25 mode. If already set, do nothing. --set_80x25: -- movw $0x5019, force_size # Override possibly broken BIOS --use_80x25: --#ifdef CONFIG_VIDEO_400_HACK -- movw $0x1202, %ax # Force 400 scan lines -- movb $0x30, %bl -- int $0x10 --#else -- movb $0x0f, %ah # Get current mode ID -- int $0x10 -- cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available -- jz st80 # on CGA/MDA/HGA and is also available on EGAM -- -- cmpw $0x5003, %ax # Unknown mode, force 80x25 color -- jnz force3 -- --st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25 -- jz set80 -- -- movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc. -- orb %al, %al # Some buggy BIOS'es set 0 rows -- jz set80 -- -- cmpb $24, %al # It's hopefully correct -- jz set80 --#endif /* CONFIG_VIDEO_400_HACK */ --force3: DO_STORE -- movw $0x0003, %ax # Forced set -- int $0x10 --set80: stc -- ret -- --# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls. --set_8pixel: -- DO_STORE -- call use_80x25 # The base is 80x25 --set_8pt: -- movw $0x1112, %ax # Use 8x8 font -- xorb %bl, %bl -- int $0x10 -- movw $0x1200, %ax # Use alternate print screen -- movb $0x20, %bl -- int $0x10 -- movw $0x1201, %ax # Turn off cursor emulation -- movb $0x34, %bl -- int $0x10 -- movb $0x01, %ah # Define cursor scan lines 6-7 -- movw $0x0607, %cx -- int $0x10 --set_current: -- stc -- ret -- --# Set the 80x28 mode. This mode works on all VGA's, because it's a standard --# 80x25 mode with 14-point fonts instead of 16-point. --set_80x28: -- DO_STORE -- call use_80x25 # The base is 80x25 --set14: movw $0x1111, %ax # Use 9x14 font -- xorb %bl, %bl -- int $0x10 -- movb $0x01, %ah # Define cursor scan lines 11-12 -- movw $0x0b0c, %cx -- int $0x10 -- stc -- ret -- --# Set the 80x43 mode. This mode is works on all VGA's. --# It's a 350-scanline mode with 8-pixel font. --set_80x43: -- DO_STORE -- movw $0x1201, %ax # Set 350 scans -- movb $0x30, %bl -- int $0x10 -- movw $0x0003, %ax # Reset video mode -- int $0x10 -- jmp set_8pt # Use 8-pixel font -- --# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font. --set_80x30: -- call use_80x25 # Start with real 80x25 -- DO_STORE -- movw $0x3cc, %dx # Get CRTC port -- inb %dx, %al -- movb $0xd4, %dl -- rorb %al # Mono or color? -- jc set48a -- -- movb $0xb4, %dl --set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7) -- call outidx -- movw $0x0b06, %ax # Vertical total -- call outidx -- movw $0x3e07, %ax # (Vertical) overflow -- call outidx -- movw $0xea10, %ax # Vertical sync start -- call outidx -- movw $0xdf12, %ax # Vertical display end -- call outidx -- movw $0xe715, %ax # Vertical blank start -- call outidx -- movw $0x0416, %ax # Vertical blank end -- call outidx -- pushw %dx -- movb $0xcc, %dl # Misc output register (read) -- inb %dx, %al -- movb $0xc2, %dl # (write) -- andb $0x0d, %al # Preserve clock select bits and color bit -- orb $0xe2, %al # Set correct sync polarity -- outb %al, %dx -- popw %dx -- movw $0x501e, force_size -- stc # That's all. -- ret -- --# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font. --set_80x34: -- call set_80x30 # Set 480 scans -- call set14 # And 14-pt font -- movw $0xdb12, %ax # VGA vertical display end -- movw $0x5022, force_size --setvde: call outidx -- stc -- ret -- --# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font. --set_80x60: -- call set_80x30 # Set 480 scans -- call set_8pt # And 8-pt font -- movw $0xdf12, %ax # VGA vertical display end -- movw $0x503c, force_size -- jmp setvde -- --# Special hack for ThinkPad graphics --set_gfx: --#ifdef CONFIG_VIDEO_GFX_HACK -- movw $VIDEO_GFX_BIOS_AX, %ax -- movw $VIDEO_GFX_BIOS_BX, %bx -- int $0x10 -- movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size -- stc --#endif -- ret -- --#ifdef CONFIG_VIDEO_RETAIN -- --# Store screen contents to temporary buffer. --store_screen: -- cmpb $0, do_restore # Already stored? -- jnz stsr -- -- testb $CAN_USE_HEAP, loadflags # Have we space for storing? -- jz stsr -- -- pushw %ax -- pushw %bx -- pushw force_size # Don't force specific size -- movw $0, force_size -- call mode_params # Obtain params of current mode -- popw force_size -- movb %fs:(PARAM_VIDEO_LINES), %ah -- movb %fs:(PARAM_VIDEO_COLS), %al -- movw %ax, %bx # BX=dimensions -- mulb %ah -- movw %ax, %cx # CX=number of characters -- addw %ax, %ax # Calculate image size -- addw $modelist+1024+4, %ax -- cmpw heap_end_ptr, %ax -- jnc sts1 # Unfortunately, out of memory -- -- movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params -- leaw modelist+1024, %di -- stosw -- movw %bx, %ax -- stosw -- pushw %ds # Store the screen -- movw video_segment, %ds -- xorw %si, %si -- rep -- movsw -- popw %ds -- incb do_restore # Screen will be restored later --sts1: popw %bx -- popw %ax --stsr: ret -- --# Restore screen contents from temporary buffer. --restore_screen: -- cmpb $0, do_restore # Has the screen been stored? -- jz res1 -- -- call mode_params # Get parameters of current mode -- movb %fs:(PARAM_VIDEO_LINES), %cl -- movb %fs:(PARAM_VIDEO_COLS), %ch -- leaw modelist+1024, %si # Screen buffer -- lodsw # Set cursor position -- movw %ax, %dx -- cmpb %cl, %dh -- jc res2 -- -- movb %cl, %dh -- decb %dh --res2: cmpb %ch, %dl -- jc res3 -- -- movb %ch, %dl -- decb %dl --res3: movb $0x02, %ah -- movb $0x00, %bh -- int $0x10 -- lodsw # Display size -- movb %ah, %dl # DL=number of lines -- movb $0, %ah # BX=phys. length of orig. line -- movw %ax, %bx -- cmpb %cl, %dl # Too many? -- jc res4 -- -- pushw %ax -- movb %dl, %al -- subb %cl, %al -- mulb %bl -- addw %ax, %si -- addw %ax, %si -- popw %ax -- movb %cl, %dl --res4: cmpb %ch, %al # Too wide? -- jc res5 -- -- movb %ch, %al # AX=width of src. line --res5: movb $0, %cl -- xchgb %ch, %cl -- movw %cx, %bp # BP=width of dest. line -- pushw %es -- movw video_segment, %es -- xorw %di, %di # Move the data -- addw %bx, %bx # Convert BX and BP to _bytes_ -- addw %bp, %bp --res6: pushw %si -- pushw %di -- movw %ax, %cx -- rep -- movsw -- popw %di -- popw %si -- addw %bp, %di -- addw %bx, %si -- decb %dl -- jnz res6 -- -- popw %es # Done --res1: ret --#endif /* CONFIG_VIDEO_RETAIN */ -- --# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port) --outidx: outb %al, %dx -- pushw %ax -- movb %ah, %al -- incw %dx -- outb %al, %dx -- decw %dx -- popw %ax -- ret -- --# Build the table of video modes (stored after the setup.S code at the --# `modelist' label. Each video mode record looks like: --# .word MODE-ID (our special mode ID (see above)) --# .byte rows (number of rows) --# .byte columns (number of columns) --# Returns address of the end of the table in DI, the end is marked --# with a ASK_VGA ID. --mode_table: -- movw mt_end, %di # Already filled? -- orw %di, %di -- jnz mtab1x -- -- leaw modelist, %di # Store standard modes: -- movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL) -- stosl -- movb adapter, %al # CGA/MDA/HGA -- no more modes -- orb %al, %al -- jz mtabe -- -- decb %al -- jnz mtabv -- -- movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode -- stosl -- jmp mtabe -- --mtab1x: jmp mtab1 -- --mtabv: leaw vga_modes, %si # All modes for std VGA -- movw $vga_modes_end-vga_modes, %cx -- rep # I'm unable to use movsw as I don't know how to store a half -- movsb # of the expression above to cx without using explicit shr. -- -- cmpb $0, scanning # Mode scan requested? -- jz mscan1 -- -- call mode_scan --mscan1: -- --#ifdef CONFIG_VIDEO_LOCAL -- call local_modes --#endif /* CONFIG_VIDEO_LOCAL */ -- --#ifdef CONFIG_VIDEO_VESA -- call vesa_modes # Detect VESA VGA modes --#endif /* CONFIG_VIDEO_VESA */ -- --#ifdef CONFIG_VIDEO_SVGA -- cmpb $0, scanning # Bypass when scanning -- jnz mscan2 -- -- call svga_modes # Detect SVGA cards & modes --mscan2: --#endif /* CONFIG_VIDEO_SVGA */ -- --mtabe: -- --#ifdef CONFIG_VIDEO_COMPACT -- leaw modelist, %si -- movw %di, %dx -- movw %si, %di --cmt1: cmpw %dx, %si # Scan all modes -- jz cmt2 -- -- leaw modelist, %bx # Find in previous entries -- movw 2(%si), %cx --cmt3: cmpw %bx, %si -- jz cmt4 -- -- cmpw 2(%bx), %cx # Found => don't copy this entry -- jz cmt5 -- -- addw $4, %bx -- jmp cmt3 -- --cmt4: movsl # Copy entry -- jmp cmt1 -- --cmt5: addw $4, %si # Skip entry -- jmp cmt1 -- --cmt2: --#endif /* CONFIG_VIDEO_COMPACT */ -- -- movw $ASK_VGA, (%di) # End marker -- movw %di, mt_end --mtab1: leaw modelist, %si # SI=mode list, DI=list end --ret0: ret -- --# Modes usable on all standard VGAs --vga_modes: -- .word VIDEO_8POINT -- .word 0x5032 # 80x50 -- .word VIDEO_80x43 -- .word 0x502b # 80x43 -- .word VIDEO_80x28 -- .word 0x501c # 80x28 -- .word VIDEO_80x30 -- .word 0x501e # 80x30 -- .word VIDEO_80x34 -- .word 0x5022 # 80x34 -- .word VIDEO_80x60 -- .word 0x503c # 80x60 --#ifdef CONFIG_VIDEO_GFX_HACK -- .word VIDEO_GFX_HACK -- .word VIDEO_GFX_DUMMY_RESOLUTION --#endif -- --vga_modes_end: --# Detect VESA modes. -- --#ifdef CONFIG_VIDEO_VESA --vesa_modes: -- cmpb $2, adapter # VGA only -- jnz ret0 -- -- movw %di, %bp # BP=original mode table end -- addw $0x200, %di # Buffer space -- movw $0x4f00, %ax # VESA Get card info call -- int $0x10 -- movw %bp, %di -- cmpw $0x004f, %ax # Successful? -- jnz ret0 -- -- cmpw $0x4556, 0x200(%di) -- jnz ret0 -- -- cmpw $0x4153, 0x202(%di) -- jnz ret0 -- -- movw $vesa_name, card_name # Set name to "VESA VGA" -- pushw %gs -- lgsw 0x20e(%di), %si # GS:SI=mode list -- movw $128, %cx # Iteration limit --vesa1: --# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst. --# XXX: lodsw %gs:(%si), %ax # Get next mode in the list -- gs; lodsw -- cmpw $0xffff, %ax # End of the table? -- jz vesar -- -- cmpw $0x0080, %ax # Check validity of mode ID -- jc vesa2 -- -- orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff -- jz vesan # Certain BIOSes report 0x80-0xff! -- -- cmpw $0x0800, %ax -- jnc vesae -- --vesa2: pushw %cx -- movw %ax, %cx # Get mode information structure -- movw $0x4f01, %ax -- int $0x10 -- movw %cx, %bx # BX=mode number -- addb $VIDEO_FIRST_VESA>>8, %bh -- popw %cx -- cmpw $0x004f, %ax -- jnz vesan # Don't report errors (buggy BIOSES) -- -- movb (%di), %al # Check capabilities. We require -- andb $0x19, %al # a color text mode. -- cmpb $0x09, %al -- jnz vesan -- -- cmpw $0xb800, 8(%di) # Standard video memory address required -- jnz vesan -- -- testb $2, (%di) # Mode characteristics supplied? -- movw %bx, (%di) # Store mode number -- jz vesa3 -- -- xorw %dx, %dx -- movw 0x12(%di), %bx # Width -- orb %bh, %bh -- jnz vesan -- -- movb %bl, 0x3(%di) -- movw 0x14(%di), %ax # Height -- orb %ah, %ah -- jnz vesan -- -- movb %al, 2(%di) -- mulb %bl -- cmpw $8193, %ax # Small enough for Linux console driver? -- jnc vesan -- -- jmp vesaok -- --vesa3: subw $0x8108, %bx # This mode has no detailed info specified, -- jc vesan # so it must be a standard VESA mode. -- -- cmpw $5, %bx -- jnc vesan -- -- movw vesa_text_mode_table(%bx), %ax -- movw %ax, 2(%di) --vesaok: addw $4, %di # The mode is valid. Store it. --vesan: loop vesa1 # Next mode. Limit exceeded => error --vesae: leaw vesaer, %si -- call prtstr -- movw %bp, %di # Discard already found modes. --vesar: popw %gs -- ret -- --# Dimensions of standard VESA text modes --vesa_text_mode_table: -- .byte 60, 80 # 0108 -- .byte 25, 132 # 0109 -- .byte 43, 132 # 010A -- .byte 50, 132 # 010B -- .byte 60, 132 # 010C --#endif /* CONFIG_VIDEO_VESA */ -- --# Scan for video modes. A bit dirty, but should work. --mode_scan: -- movw $0x0100, %cx # Start with mode 0 --scm1: movb $0, %ah # Test the mode -- movb %cl, %al -- int $0x10 -- movb $0x0f, %ah -- int $0x10 -- cmpb %cl, %al -- jnz scm2 # Mode not set -- -- movw $0x3c0, %dx # Test if it's a text mode -- movb $0x10, %al # Mode bits -- call inidx -- andb $0x03, %al -- jnz scm2 -- -- movb $0xce, %dl # Another set of mode bits -- movb $0x06, %al -- call inidx -- shrb %al -- jc scm2 -- -- movb $0xd4, %dl # Cursor location -- movb $0x0f, %al -- call inidx -- orb %al, %al -- jnz scm2 -- -- movw %cx, %ax # Ok, store the mode -- stosw -- movb %gs:(0x484), %al # Number of rows -- incb %al -- stosb -- movw %gs:(0x44a), %ax # Number of columns -- stosb --scm2: incb %cl -- jns scm1 -- -- movw $0x0003, %ax # Return back to mode 3 -- int $0x10 -- ret -- --tstidx: outw %ax, %dx # OUT DX,AX and inidx --inidx: outb %al, %dx # Read from indexed VGA register -- incw %dx # AL=index, DX=index reg port -> AL=data -- inb %dx, %al -- decw %dx -- ret -- --# Try to detect type of SVGA card and supply (usually approximate) video --# mode table for it. -- --#ifdef CONFIG_VIDEO_SVGA --svga_modes: -- leaw svga_table, %si # Test all known SVGA adapters --dosvga: lodsw -- movw %ax, %bp # Default mode table -- orw %ax, %ax -- jz didsv1 -- -- lodsw # Pointer to test routine -- pushw %si -- pushw %di -- pushw %es -- movw $0xc000, %bx -- movw %bx, %es -- call *%ax # Call test routine -- popw %es -- popw %di -- popw %si -- orw %bp, %bp -- jz dosvga -- -- movw %bp, %si # Found, copy the modes -- movb svga_prefix, %ah --cpsvga: lodsb -- orb %al, %al -- jz didsv -- -- stosw -- movsw -- jmp cpsvga -- --didsv: movw %si, card_name # Store pointer to card name --didsv1: ret -- --# Table of all known SVGA cards. For each card, we store a pointer to --# a table of video modes supported by the card and a pointer to a routine --# used for testing of presence of the card. The video mode table is always --# followed by the name of the card or the chipset. --svga_table: -- .word ati_md, ati_test -- .word oak_md, oak_test -- .word paradise_md, paradise_test -- .word realtek_md, realtek_test -- .word s3_md, s3_test -- .word chips_md, chips_test -- .word video7_md, video7_test -- .word cirrus5_md, cirrus5_test -- .word cirrus6_md, cirrus6_test -- .word cirrus1_md, cirrus1_test -- .word ahead_md, ahead_test -- .word everex_md, everex_test -- .word genoa_md, genoa_test -- .word trident_md, trident_test -- .word tseng_md, tseng_test -- .word 0 -- --# Test routines and mode tables: -- --# S3 - The test algorithm was taken from the SuperProbe package --# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org --s3_test: -- movw $0x0f35, %cx # we store some constants in cl/ch -- movw $0x03d4, %dx -- movb $0x38, %al -- call inidx -- movb %al, %bh # store current CRT-register 0x38 -- movw $0x0038, %ax -- call outidx # disable writing to special regs -- movb %cl, %al # check whether we can write special reg 0x35 -- call inidx -- movb %al, %bl # save the current value of CRT reg 0x35 -- andb $0xf0, %al # clear bits 0-3 -- movb %al, %ah -- movb %cl, %al # and write it to CRT reg 0x35 -- call outidx -- call inidx # now read it back -- andb %ch, %al # clear the upper 4 bits -- jz s3_2 # the first test failed. But we have a -- -- movb %bl, %ah # second chance -- movb %cl, %al -- call outidx -- jmp s3_1 # do the other tests -- --s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35 -- orb %bl, %ah # set the upper 4 bits of ah with the orig value -- call outidx # write ... -- call inidx # ... and reread -- andb %cl, %al # turn off the upper 4 bits -- pushw %ax -- movb %bl, %ah # restore old value in register 0x35 -- movb %cl, %al -- call outidx -- popw %ax -- cmpb %ch, %al # setting lower 4 bits was successful => bad -- je no_s3 # writing is allowed => this is not an S3 -- --s3_1: movw $0x4838, %ax # allow writing to special regs by putting -- call outidx # magic number into CRT-register 0x38 -- movb %cl, %al # check whether we can write special reg 0x35 -- call inidx -- movb %al, %bl -- andb $0xf0, %al -- movb %al, %ah -- movb %cl, %al -- call outidx -- call inidx -- andb %ch, %al -- jnz no_s3 # no, we can't write => no S3 -- -- movw %cx, %ax -- orb %bl, %ah -- call outidx -- call inidx -- andb %ch, %al -- pushw %ax -- movb %bl, %ah # restore old value in register 0x35 -- movb %cl, %al -- call outidx -- popw %ax -- cmpb %ch, %al -- jne no_s31 # writing not possible => no S3 -- movb $0x30, %al -- call inidx # now get the S3 id ... -- leaw idS3, %di -- movw $0x10, %cx -- repne -- scasb -- je no_s31 -- -- movb %bh, %ah -- movb $0x38, %al -- jmp s3rest -- --no_s3: movb $0x35, %al # restore CRT register 0x35 -- movb %bl, %ah -- call outidx --no_s31: xorw %bp, %bp # Detection failed --s3rest: movb %bh, %ah -- movb $0x38, %al # restore old value of CRT register 0x38 -- jmp outidx -- --idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 -- .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0 -- --s3_md: .byte 0x54, 0x2b, 0x84 -- .byte 0x55, 0x19, 0x84 -- .byte 0 -- .ascii "S3" -- .byte 0 -- --# ATI cards. --ati_test: -- leaw idati, %si -- movw $0x31, %di -- movw $0x09, %cx -- repe -- cmpsb -- je atiok -- -- xorw %bp, %bp --atiok: ret -- --idati: .ascii "761295520" -- --ati_md: .byte 0x23, 0x19, 0x84 -- .byte 0x33, 0x2c, 0x84 -- .byte 0x22, 0x1e, 0x64 -- .byte 0x21, 0x19, 0x64 -- .byte 0x58, 0x21, 0x50 -- .byte 0x5b, 0x1e, 0x50 -- .byte 0 -- .ascii "ATI" -- .byte 0 -- --# AHEAD --ahead_test: -- movw $0x200f, %ax -- movw $0x3ce, %dx -- outw %ax, %dx -- incw %dx -- inb %dx, %al -- cmpb $0x20, %al -- je isahed -- -- cmpb $0x21, %al -- je isahed -- -- xorw %bp, %bp --isahed: ret -- --ahead_md: -- .byte 0x22, 0x2c, 0x84 -- .byte 0x23, 0x19, 0x84 -- .byte 0x24, 0x1c, 0x84 -- .byte 0x2f, 0x32, 0xa0 -- .byte 0x32, 0x22, 0x50 -- .byte 0x34, 0x42, 0x50 -- .byte 0 -- .ascii "Ahead" -- .byte 0 -- --# Chips & Tech. --chips_test: -- movw $0x3c3, %dx -- inb %dx, %al -- orb $0x10, %al -- outb %al, %dx -- movw $0x104, %dx -- inb %dx, %al -- movb %al, %bl -- movw $0x3c3, %dx -- inb %dx, %al -- andb $0xef, %al -- outb %al, %dx -- cmpb $0xa5, %bl -- je cantok -- -- xorw %bp, %bp --cantok: ret -- --chips_md: -- .byte 0x60, 0x19, 0x84 -- .byte 0x61, 0x32, 0x84 -- .byte 0 -- .ascii "Chips & Technologies" -- .byte 0 -- --# Cirrus Logic 5X0 --cirrus1_test: -- movw $0x3d4, %dx -- movb $0x0c, %al -- outb %al, %dx -- incw %dx -- inb %dx, %al -- movb %al, %bl -- xorb %al, %al -- outb %al, %dx -- decw %dx -- movb $0x1f, %al -- outb %al, %dx -- incw %dx -- inb %dx, %al -- movb %al, %bh -- xorb %ah, %ah -- shlb $4, %al -- movw %ax, %cx -- movb %bh, %al -- shrb $4, %al -- addw %ax, %cx -- shlw $8, %cx -- addw $6, %cx -- movw %cx, %ax -- movw $0x3c4, %dx -- outw %ax, %dx -- incw %dx -- inb %dx, %al -- andb %al, %al -- jnz nocirr -- -- movb %bh, %al -- outb %al, %dx -- inb %dx, %al -- cmpb $0x01, %al -- je iscirr -- --nocirr: xorw %bp, %bp --iscirr: movw $0x3d4, %dx -- movb %bl, %al -- xorb %ah, %ah -- shlw $8, %ax -- addw $0x0c, %ax -- outw %ax, %dx -- ret -- --cirrus1_md: -- .byte 0x1f, 0x19, 0x84 -- .byte 0x20, 0x2c, 0x84 -- .byte 0x22, 0x1e, 0x84 -- .byte 0x31, 0x25, 0x64 -- .byte 0 -- .ascii "Cirrus Logic 5X0" -- .byte 0 -- --# Cirrus Logic 54XX --cirrus5_test: -- movw $0x3c4, %dx -- movb $6, %al -- call inidx -- movb %al, %bl # BL=backup -- movw $6, %ax -- call tstidx -- cmpb $0x0f, %al -- jne c5fail -- -- movw $0x1206, %ax -- call tstidx -- cmpb $0x12, %al -- jne c5fail -- -- movb $0x1e, %al -- call inidx -- movb %al, %bh -- movb %bh, %ah -- andb $0xc0, %ah -- movb $0x1e, %al -- call tstidx -- andb $0x3f, %al -- jne c5xx -- -- movb $0x1e, %al -- movb %bh, %ah -- orb $0x3f, %ah -- call tstidx -- xorb $0x3f, %al -- andb $0x3f, %al --c5xx: pushf -- movb $0x1e, %al -- movb %bh, %ah -- outw %ax, %dx -- popf -- je c5done -- --c5fail: xorw %bp, %bp --c5done: movb $6, %al -- movb %bl, %ah -- outw %ax, %dx -- ret -- --cirrus5_md: -- .byte 0x14, 0x19, 0x84 -- .byte 0x54, 0x2b, 0x84 -- .byte 0 -- .ascii "Cirrus Logic 54XX" -- .byte 0 -- --# Cirrus Logic 64XX -- no known extra modes, but must be identified, because --# it's misidentified by the Ahead test. --cirrus6_test: -- movw $0x3ce, %dx -- movb $0x0a, %al -- call inidx -- movb %al, %bl # BL=backup -- movw $0xce0a, %ax -- call tstidx -- orb %al, %al -- jne c2fail -- -- movw $0xec0a, %ax -- call tstidx -- cmpb $0x01, %al -- jne c2fail -- -- movb $0xaa, %al -- call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's. -- shrb $4, %al -- subb $4, %al -- jz c6done -- -- decb %al -- jz c6done -- -- subb $2, %al -- jz c6done -- -- decb %al -- jz c6done -- --c2fail: xorw %bp, %bp --c6done: movb $0x0a, %al -- movb %bl, %ah -- outw %ax, %dx -- ret -- --cirrus6_md: -- .byte 0 -- .ascii "Cirrus Logic 64XX" -- .byte 0 -- --# Everex / Trident --everex_test: -- movw $0x7000, %ax -- xorw %bx, %bx -- int $0x10 -- cmpb $0x70, %al -- jne noevrx -- -- shrw $4, %dx -- cmpw $0x678, %dx -- je evtrid -- -- cmpw $0x236, %dx -- jne evrxok -- --evtrid: leaw trident_md, %bp --evrxok: ret -- --noevrx: xorw %bp, %bp -- ret -- --everex_md: -- .byte 0x03, 0x22, 0x50 -- .byte 0x04, 0x3c, 0x50 -- .byte 0x07, 0x2b, 0x64 -- .byte 0x08, 0x4b, 0x64 -- .byte 0x0a, 0x19, 0x84 -- .byte 0x0b, 0x2c, 0x84 -- .byte 0x16, 0x1e, 0x50 -- .byte 0x18, 0x1b, 0x64 -- .byte 0x21, 0x40, 0xa0 -- .byte 0x40, 0x1e, 0x84 -- .byte 0 -- .ascii "Everex/Trident" -- .byte 0 -- --# Genoa. --genoa_test: -- leaw idgenoa, %si # Check Genoa 'clues' -- xorw %ax, %ax -- movb %es:(0x37), %al -- movw %ax, %di -- movw $0x04, %cx -- decw %si -- decw %di --l1: incw %si -- incw %di -- movb (%si), %al -- testb %al, %al -- jz l2 -- -- cmpb %es:(%di), %al --l2: loope l1 -- orw %cx, %cx -- je isgen -- -- xorw %bp, %bp --isgen: ret -- --idgenoa: .byte 0x77, 0x00, 0x99, 0x66 -- --genoa_md: -- .byte 0x58, 0x20, 0x50 -- .byte 0x5a, 0x2a, 0x64 -- .byte 0x60, 0x19, 0x84 -- .byte 0x61, 0x1d, 0x84 -- .byte 0x62, 0x20, 0x84 -- .byte 0x63, 0x2c, 0x84 -- .byte 0x64, 0x3c, 0x84 -- .byte 0x6b, 0x4f, 0x64 -- .byte 0x72, 0x3c, 0x50 -- .byte 0x74, 0x42, 0x50 -- .byte 0x78, 0x4b, 0x64 -- .byte 0 -- .ascii "Genoa" -- .byte 0 -- --# OAK --oak_test: -- leaw idoakvga, %si -- movw $0x08, %di -- movw $0x08, %cx -- repe -- cmpsb -- je isoak -- -- xorw %bp, %bp --isoak: ret -- --idoakvga: .ascii "OAK VGA " -- --oak_md: .byte 0x4e, 0x3c, 0x50 -- .byte 0x4f, 0x3c, 0x84 -- .byte 0x50, 0x19, 0x84 -- .byte 0x51, 0x2b, 0x84 -- .byte 0 -- .ascii "OAK" -- .byte 0 -- --# WD Paradise. --paradise_test: -- leaw idparadise, %si -- movw $0x7d, %di -- movw $0x04, %cx -- repe -- cmpsb -- je ispara -- -- xorw %bp, %bp --ispara: ret -- --idparadise: .ascii "VGA=" -- --paradise_md: -- .byte 0x41, 0x22, 0x50 -- .byte 0x47, 0x1c, 0x84 -- .byte 0x55, 0x19, 0x84 -- .byte 0x54, 0x2c, 0x84 -- .byte 0 -- .ascii "Paradise" -- .byte 0 -- --# Trident. --trident_test: -- movw $0x3c4, %dx -- movb $0x0e, %al -- outb %al, %dx -- incw %dx -- inb %dx, %al -- xchgb %al, %ah -- xorb %al, %al -- outb %al, %dx -- inb %dx, %al -- xchgb %ah, %al -- movb %al, %bl # Strange thing ... in the book this wasn't -- andb $0x02, %bl # necessary but it worked on my card which -- jz setb2 # is a trident. Without it the screen goes -- # blurred ... -- andb $0xfd, %al -- jmp clrb2 -- --setb2: orb $0x02, %al --clrb2: outb %al, %dx -- andb $0x0f, %ah -- cmpb $0x02, %ah -- je istrid -- -- xorw %bp, %bp --istrid: ret -- --trident_md: -- .byte 0x50, 0x1e, 0x50 -- .byte 0x51, 0x2b, 0x50 -- .byte 0x52, 0x3c, 0x50 -- .byte 0x57, 0x19, 0x84 -- .byte 0x58, 0x1e, 0x84 -- .byte 0x59, 0x2b, 0x84 -- .byte 0x5a, 0x3c, 0x84 -- .byte 0 -- .ascii "Trident" -- .byte 0 -- --# Tseng. --tseng_test: -- movw $0x3cd, %dx -- inb %dx, %al # Could things be this simple ! :-) -- movb %al, %bl -- movb $0x55, %al -- outb %al, %dx -- inb %dx, %al -- movb %al, %ah -- movb %bl, %al -- outb %al, %dx -- cmpb $0x55, %ah -- je istsen -- --isnot: xorw %bp, %bp --istsen: ret -- --tseng_md: -- .byte 0x26, 0x3c, 0x50 -- .byte 0x2a, 0x28, 0x64 -- .byte 0x23, 0x19, 0x84 -- .byte 0x24, 0x1c, 0x84 -- .byte 0x22, 0x2c, 0x84 -- .byte 0x21, 0x3c, 0x84 -- .byte 0 -- .ascii "Tseng" -- .byte 0 -- --# Video7. --video7_test: -- movw $0x3cc, %dx -- inb %dx, %al -- movw $0x3b4, %dx -- andb $0x01, %al -- jz even7 -- -- movw $0x3d4, %dx --even7: movb $0x0c, %al -- outb %al, %dx -- incw %dx -- inb %dx, %al -- movb %al, %bl -- movb $0x55, %al -- outb %al, %dx -- inb %dx, %al -- decw %dx -- movb $0x1f, %al -- outb %al, %dx -- incw %dx -- inb %dx, %al -- movb %al, %bh -- decw %dx -- movb $0x0c, %al -- outb %al, %dx -- incw %dx -- movb %bl, %al -- outb %al, %dx -- movb $0x55, %al -- xorb $0xea, %al -- cmpb %bh, %al -- jne isnot -- -- movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching -- ret -- --video7_md: -- .byte 0x40, 0x2b, 0x50 -- .byte 0x43, 0x3c, 0x50 -- .byte 0x44, 0x3c, 0x64 -- .byte 0x41, 0x19, 0x84 -- .byte 0x42, 0x2c, 0x84 -- .byte 0x45, 0x1c, 0x84 -- .byte 0 -- .ascii "Video 7" -- .byte 0 -- --# Realtek VGA --realtek_test: -- leaw idrtvga, %si -- movw $0x45, %di -- movw $0x0b, %cx -- repe -- cmpsb -- je isrt -- -- xorw %bp, %bp --isrt: ret -- --idrtvga: .ascii "REALTEK VGA" -- --realtek_md: -- .byte 0x1a, 0x3c, 0x50 -- .byte 0x1b, 0x19, 0x84 -- .byte 0x1c, 0x1e, 0x84 -- .byte 0x1d, 0x2b, 0x84 -- .byte 0x1e, 0x3c, 0x84 -- .byte 0 -- .ascii "REALTEK" -- .byte 0 -- --#endif /* CONFIG_VIDEO_SVGA */ -- --# User-defined local mode table (VGA only) --#ifdef CONFIG_VIDEO_LOCAL --local_modes: -- leaw local_mode_table, %si --locm1: lodsw -- orw %ax, %ax -- jz locm2 -- -- stosw -- movsw -- jmp locm1 -- --locm2: ret -- --# This is the table of local video modes which can be supplied manually --# by the user. Each entry consists of mode ID (word) and dimensions --# (byte for column count and another byte for row count). These modes --# are placed before all SVGA and VESA modes and override them if table --# compacting is enabled. The table must end with a zero word followed --# by NUL-terminated video adapter name. --local_mode_table: -- .word 0x0100 # Example: 40x25 -- .byte 25,40 -- .word 0 -- .ascii "Local" -- .byte 0 --#endif /* CONFIG_VIDEO_LOCAL */ -- --# Read a key and return the ASCII code in al, scan code in ah --getkey: xorb %ah, %ah -- int $0x16 -- ret -- --# Read a key with a timeout of 30 seconds. --# The hardware clock is used to get the time. --getkt: call gettime -- addb $30, %al # Wait 30 seconds -- cmpb $60, %al -- jl lminute -- -- subb $60, %al --lminute: -- movb %al, %cl --again: movb $0x01, %ah -- int $0x16 -- jnz getkey # key pressed, so get it -- -- call gettime -- cmpb %cl, %al -- jne again -- -- movb $0x20, %al # timeout, return `space' -- ret -- --# Flush the keyboard buffer --flush: movb $0x01, %ah -- int $0x16 -- jz empty -- -- xorb %ah, %ah -- int $0x16 -- jmp flush -- --empty: ret -- --# Print hexadecimal number. --prthw: pushw %ax -- movb %ah, %al -- call prthb -- popw %ax --prthb: pushw %ax -- shrb $4, %al -- call prthn -- popw %ax -- andb $0x0f, %al --prthn: cmpb $0x0a, %al -- jc prth1 -- -- addb $0x07, %al --prth1: addb $0x30, %al -- jmp prtchr -- --# Print decimal number in al --prtdec: pushw %ax -- pushw %cx -- xorb %ah, %ah -- movb $0x0a, %cl -- idivb %cl -- cmpb $0x09, %al -- jbe lt100 -- -- call prtdec -- jmp skip10 -- --lt100: addb $0x30, %al -- call prtchr --skip10: movb %ah, %al -- addb $0x30, %al -- call prtchr -- popw %cx -- popw %ax -- ret -- --store_edid: --#ifdef CONFIG_FIRMWARE_EDID -- pushw %es # just save all registers -- pushw %ax -- pushw %bx -- pushw %cx -- pushw %dx -- pushw %di -- -- pushw %fs -- popw %es -- -- movl $0x13131313, %eax # memset block with 0x13 -- movw $32, %cx -- movw $0x140, %di -- cld -- rep -- stosl -- -- cmpw $0x0200, vbe_version # only do EDID on >= VBE2.0 -- jl no_edid -- -- pushw %es # save ES -- xorw %di, %di # Report Capability -- pushw %di -- popw %es # ES:DI must be 0:0 -- movw $0x4f15, %ax -- xorw %bx, %bx -- xorw %cx, %cx -- int $0x10 -- popw %es # restore ES -- -- cmpb $0x00, %ah # call successful -- jne no_edid -- -- cmpb $0x4f, %al # function supported -- jne no_edid -- -- movw $0x4f15, %ax # do VBE/DDC -- movw $0x01, %bx -- movw $0x00, %cx -- movw $0x00, %dx -- movw $0x140, %di -- int $0x10 -- --no_edid: -- popw %di # restore all registers -- popw %dx -- popw %cx -- popw %bx -- popw %ax -- popw %es --#endif -- ret -- --# VIDEO_SELECT-only variables --mt_end: .word 0 # End of video mode table if built --edit_buf: .space 6 # Line editor buffer --card_name: .word 0 # Pointer to adapter name --scanning: .byte 0 # Performing mode scan --do_restore: .byte 0 # Screen contents altered during mode change --svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes --graphic_mode: .byte 0 # Graphic mode with a linear frame buffer --dac_size: .byte 6 # DAC bit depth --vbe_version: .word 0 # VBE bios version -- --# Status messages --keymsg: .ascii "Press to see video modes available, " -- .ascii " to continue or wait 30 secs" -- .byte 0x0d, 0x0a, 0 -- --listhdr: .byte 0x0d, 0x0a -- .ascii "Mode: COLSxROWS:" -- --crlft: .byte 0x0d, 0x0a, 0 -- --prompt: .byte 0x0d, 0x0a -- .asciz "Enter mode number or `scan': " -- --unknt: .asciz "Unknown mode ID. Try again." -- --badmdt: .ascii "You passed an undefined mode number." -- .byte 0x0d, 0x0a, 0 -- --vesaer: .ascii "Error: Scanning of VESA modes failed. Please " -- .ascii "report to ." -- .byte 0x0d, 0x0a, 0 -- --old_name: .asciz "CGA/MDA/HGA" -- --ega_name: .asciz "EGA" -- --svga_name: .ascii " " -- --vga_name: .asciz "VGA" -- --vesa_name: .asciz "VESA" -- --name_bann: .asciz "Video adapter: " --#endif /* CONFIG_VIDEO_SELECT */ -- --# Other variables: --adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA --video_segment: .word 0xb800 # Video memory segment --force_size: .word 0 # Use this size instead of the one in BIOS vars ---- /dev/null -+++ b/arch/i386/boot/video.c -@@ -0,0 +1,456 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/video.c -+ * -+ * Select video mode -+ */ -+ -+#include "boot.h" -+#include "video.h" -+#include "vesa.h" -+ -+/* -+ * Mode list variables -+ */ -+static struct card_info cards[]; /* List of cards to probe for */ -+ -+/* -+ * Common variables -+ */ -+int adapter; /* 0=CGA/MDA/HGC, 1=EGA, 2=VGA+ */ -+u16 video_segment; -+int force_x, force_y; /* Don't query the BIOS for cols/rows */ -+ -+int do_restore = 0; /* Screen contents changed during mode flip */ -+int graphic_mode; /* Graphic mode with linear frame buffer */ -+ -+static void store_cursor_position(void) -+{ -+ u16 curpos; -+ u16 ax, bx; -+ -+ ax = 0x0300; -+ bx = 0; -+ asm(INT10 -+ : "=d" (curpos), "+a" (ax), "+b" (bx) -+ : : "ecx", "esi", "edi"); -+ -+ boot_params.screen_info.orig_x = curpos; -+ boot_params.screen_info.orig_y = curpos >> 8; -+} -+ -+static void store_video_mode(void) -+{ -+ u16 ax, page; -+ -+ /* N.B.: the saving of the video page here is a bit silly, -+ since we pretty much assume page 0 everywhere. */ -+ ax = 0x0f00; -+ asm(INT10 -+ : "+a" (ax), "=b" (page) -+ : : "ecx", "edx", "esi", "edi"); -+ -+ /* Not all BIOSes are clean with respect to the top bit */ -+ boot_params.screen_info.orig_video_mode = ax & 0x7f; -+ boot_params.screen_info.orig_video_page = page; -+} -+ -+/* -+ * Store the video mode parameters for later usage by the kernel. -+ * This is done by asking the BIOS except for the rows/columns -+ * parameters in the default 80x25 mode -- these are set directly, -+ * because some very obscure BIOSes supply insane values. -+ */ -+static void store_mode_params(void) -+{ -+ u16 font_size; -+ int x, y; -+ -+ /* For graphics mode, it is up to the mode-setting driver -+ (currently only video-vesa.c) to store the parameters */ -+ if (graphic_mode) -+ return; -+ -+ store_cursor_position(); -+ store_video_mode(); -+ -+ if (boot_params.screen_info.orig_video_mode == 0x07) { -+ /* MDA, HGC, or VGA in monochrome mode */ -+ video_segment = 0xb000; -+ } else { -+ /* CGA, EGA, VGA and so forth */ -+ video_segment = 0xb800; -+ } -+ -+ set_fs(0); -+ font_size = rdfs16(0x485); /* Font size, BIOS area */ -+ boot_params.screen_info.orig_video_points = font_size; -+ -+ x = rdfs16(0x44a); -+ y = (adapter == ADAPTER_CGA) ? 25 : rdfs8(0x484)+1; -+ -+ if (force_x) -+ x = force_x; -+ if (force_y) -+ y = force_y; -+ -+ boot_params.screen_info.orig_video_cols = x; -+ boot_params.screen_info.orig_video_lines = y; -+} -+ -+/* Probe the video drivers and have them generate their mode lists. */ -+static void probe_cards(int unsafe) -+{ -+ struct card_info *card; -+ static u8 probed[2]; -+ -+ if (probed[unsafe]) -+ return; -+ -+ probed[unsafe] = 1; -+ -+ for (card = video_cards; card < video_cards_end; card++) { -+ if (card->unsafe == unsafe) { -+ if (card->probe) -+ card->nmodes = card->probe(); -+ else -+ card->nmodes = 0; -+ } -+ } -+} -+ -+/* Test if a mode is defined */ -+int mode_defined(u16 mode) -+{ -+ struct card_info *card; -+ struct mode_info *mi; -+ int i; -+ -+ for (card = video_cards; card < video_cards_end; card++) { -+ mi = card->modes; -+ for (i = 0; i < card->nmodes; i++, mi++) { -+ if (mi->mode == mode) -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+/* Set mode (without recalc) */ -+static int raw_set_mode(u16 mode) -+{ -+ int nmode, i; -+ struct card_info *card; -+ struct mode_info *mi; -+ -+ /* Drop the recalc bit if set */ -+ mode &= ~VIDEO_RECALC; -+ -+ /* Scan for mode based on fixed ID, position, or resolution */ -+ nmode = 0; -+ for (card = video_cards; card < video_cards_end; card++) { -+ mi = card->modes; -+ for (i = 0; i < card->nmodes; i++, mi++) { -+ int visible = mi->x || mi->y; -+ -+ if ((mode == nmode && visible) || -+ mode == mi->mode || -+ mode == (mi->y << 8)+mi->x) -+ return card->set_mode(mi); -+ -+ if (visible) -+ nmode++; -+ } -+ } -+ -+ /* Nothing found? Is it an "exceptional" (unprobed) mode? */ -+ for (card = video_cards; card < video_cards_end; card++) { -+ if (mode >= card->xmode_first && -+ mode < card->xmode_first+card->xmode_n) { -+ struct mode_info mix; -+ mix.mode = mode; -+ mix.x = mix.y = 0; -+ return card->set_mode(&mix); -+ } -+ } -+ -+ /* Otherwise, failure... */ -+ return -1; -+} -+ -+/* -+ * Recalculate the vertical video cutoff (hack!) -+ */ -+static void vga_recalc_vertical(void) -+{ -+ unsigned int font_size, rows; -+ u16 crtc; -+ u8 ov; -+ -+ set_fs(0); -+ font_size = rdfs8(0x485); /* BIOS: font size (pixels) */ -+ rows = force_y ? force_y : rdfs8(0x484)+1; /* Text rows */ -+ -+ rows *= font_size; /* Visible scan lines */ -+ rows--; /* ... minus one */ -+ -+ crtc = vga_crtc(); -+ -+ out_idx((u8)rows, crtc, 0x12); /* Lower height register */ -+ ov = in_idx(crtc, 0x07); /* Overflow register */ -+ ov &= 0xbd; -+ ov |= (rows >> (8-1)) & 0x02; -+ ov |= (rows >> (9-6)) & 0x40; -+ out_idx(ov, crtc, 0x07); -+} -+ -+/* Set mode (with recalc if specified) */ -+static int set_mode(u16 mode) -+{ -+ int rv; -+ -+ /* Very special mode numbers... */ -+ if (mode == VIDEO_CURRENT_MODE) -+ return 0; /* Nothing to do... */ -+ else if (mode == NORMAL_VGA) -+ mode = VIDEO_80x25; -+ else if (mode == EXTENDED_VGA) -+ mode = VIDEO_8POINT; -+ -+ rv = raw_set_mode(mode); -+ if (rv) -+ return rv; -+ -+ if (mode & VIDEO_RECALC) -+ vga_recalc_vertical(); -+ -+ return 0; -+} -+ -+static unsigned int get_entry(void) -+{ -+ char entry_buf[4]; -+ int i, len = 0; -+ int key; -+ unsigned int v; -+ -+ do { -+ key = getchar(); -+ -+ if (key == '\b') { -+ if (len > 0) { -+ puts("\b \b"); -+ len--; -+ } -+ } else if ((key >= '0' && key <= '9') || -+ (key >= 'A' && key <= 'Z') || -+ (key >= 'a' && key <= 'z')) { -+ if (len < sizeof entry_buf) { -+ entry_buf[len++] = key; -+ putchar(key); -+ } -+ } -+ } while (key != '\r'); -+ putchar('\n'); -+ -+ if (len == 0) -+ return VIDEO_CURRENT_MODE; /* Default */ -+ -+ v = 0; -+ for (i = 0; i < len; i++) { -+ v <<= 4; -+ key = entry_buf[i] | 0x20; -+ v += (key > '9') ? key-'a'+10 : key-'0'; -+ } -+ -+ return v; -+} -+ -+static void display_menu(void) -+{ -+ struct card_info *card; -+ struct mode_info *mi; -+ char ch; -+ int i; -+ -+ puts("Mode: COLSxROWS:\n"); -+ -+ ch = '0'; -+ for (card = video_cards; card < video_cards_end; card++) { -+ mi = card->modes; -+ for (i = 0; i < card->nmodes; i++, mi++) { -+ int visible = mi->x && mi->y; -+ u16 mode_id = mi->mode ? mi->mode : -+ (mi->y << 8)+mi->x; -+ -+ if (!visible) -+ continue; /* Hidden mode */ -+ -+ printf("%c %04X %3dx%-3d %s\n", -+ ch, mode_id, mi->x, mi->y, card->card_name); -+ -+ if (ch == '9') -+ ch = 'a'; -+ else if (ch == 'z' || ch == ' ') -+ ch = ' '; /* Out of keys... */ -+ else -+ ch++; -+ } -+ } -+} -+ -+#define H(x) ((x)-'a'+10) -+#define SCAN ((H('s')<<12)+(H('c')<<8)+(H('a')<<4)+H('n')) -+ -+static unsigned int mode_menu(void) -+{ -+ int key; -+ unsigned int sel; -+ -+ puts("Press to see video modes available, " -+ " to continue, or wait 30 sec\n"); -+ -+ kbd_flush(); -+ while (1) { -+ key = getchar_timeout(); -+ if (key == ' ' || key == 0) -+ return VIDEO_CURRENT_MODE; /* Default */ -+ if (key == '\r') -+ break; -+ putchar('\a'); /* Beep! */ -+ } -+ -+ -+ for (;;) { -+ display_menu(); -+ -+ puts("Enter a video mode or \"scan\" to scan for " -+ "additional modes: "); -+ sel = get_entry(); -+ if (sel != SCAN) -+ return sel; -+ -+ probe_cards(1); -+ } -+} -+ -+#ifdef CONFIG_VIDEO_RETAIN -+/* Save screen content to the heap */ -+struct saved_screen { -+ int x, y; -+ int curx, cury; -+ u16 *data; -+} saved; -+ -+static void save_screen(void) -+{ -+ /* Should be called after store_mode_params() */ -+ saved.x = boot_params.screen_info.orig_video_cols; -+ saved.y = boot_params.screen_info.orig_video_lines; -+ saved.curx = boot_params.screen_info.orig_x; -+ saved.cury = boot_params.screen_info.orig_y; -+ -+ if (heap_free() < saved.x*saved.y*sizeof(u16)+512) -+ return; /* Not enough heap to save the screen */ -+ -+ saved.data = GET_HEAP(u16, saved.x*saved.y); -+ -+ set_fs(video_segment); -+ copy_from_fs(saved.data, 0, saved.x*saved.y*sizeof(u16)); -+} -+ -+static void restore_screen(void) -+{ -+ /* Should be called after store_mode_params() */ -+ int xs = boot_params.screen_info.orig_video_cols; -+ int ys = boot_params.screen_info.orig_video_lines; -+ int y; -+ addr_t dst = 0; -+ u16 *src = saved.data; -+ u16 ax, bx, dx; -+ -+ if (graphic_mode) -+ return; /* Can't restore onto a graphic mode */ -+ -+ if (!src) -+ return; /* No saved screen contents */ -+ -+ /* Restore screen contents */ -+ -+ set_fs(video_segment); -+ for (y = 0; y < ys; y++) { -+ int npad; -+ -+ if (y < saved.y) { -+ int copy = (xs < saved.x) ? xs : saved.x; -+ copy_to_fs(dst, src, copy*sizeof(u16)); -+ dst += copy*sizeof(u16); -+ src += saved.x; -+ npad = (xs < saved.x) ? 0 : xs-saved.x; -+ } else { -+ npad = xs; -+ } -+ -+ /* Writes "npad" blank characters to -+ video_segment:dst and advances dst */ -+ asm volatile("pushw %%es ; " -+ "movw %2,%%es ; " -+ "shrw %%cx ; " -+ "jnc 1f ; " -+ "stosw \n\t" -+ "1: rep;stosl ; " -+ "popw %%es" -+ : "+D" (dst), "+c" (npad) -+ : "bdSm" (video_segment), -+ "a" (0x07200720)); -+ } -+ -+ /* Restore cursor position */ -+ ax = 0x0200; /* Set cursor position */ -+ bx = 0; /* Page number (<< 8) */ -+ dx = (saved.cury << 8)+saved.curx; -+ asm volatile(INT10 -+ : "+a" (ax), "+b" (bx), "+d" (dx) -+ : : "ecx", "esi", "edi"); -+} -+#else -+#define save_screen() ((void)0) -+#define restore_screen() ((void)0) -+#endif -+ -+void set_video(void) -+{ -+ u16 mode = boot_params.hdr.vid_mode; -+ -+ RESET_HEAP(); -+ -+ store_mode_params(); -+ save_screen(); -+ probe_cards(0); -+ -+ for (;;) { -+ if (mode == ASK_VGA) -+ mode = mode_menu(); -+ -+ if (!set_mode(mode)) -+ break; -+ -+ printf("Undefined video mode number: %x\n", mode); -+ mode = ASK_VGA; -+ } -+ vesa_store_edid(); -+ store_mode_params(); -+ -+ if (do_restore) -+ restore_screen(); -+} ---- /dev/null -+++ b/arch/i386/boot/video.h -@@ -0,0 +1,145 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/video.h -+ * -+ * Header file for the real-mode video probing code -+ */ -+ -+#ifndef BOOT_VIDEO_H -+#define BOOT_VIDEO_H -+ -+#include -+ -+/* Enable autodetection of SVGA adapters and modes. */ -+#undef CONFIG_VIDEO_SVGA -+ -+/* Enable autodetection of VESA modes */ -+#define CONFIG_VIDEO_VESA -+ -+/* Retain screen contents when switching modes */ -+#define CONFIG_VIDEO_RETAIN -+ -+/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ -+#undef CONFIG_VIDEO_400_HACK -+ -+/* This code uses an extended set of video mode numbers. These include: -+ * Aliases for standard modes -+ * NORMAL_VGA (-1) -+ * EXTENDED_VGA (-2) -+ * ASK_VGA (-3) -+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack -+ * of compatibility when extending the table. These are between 0x00 and 0xff. -+ */ -+#define VIDEO_FIRST_MENU 0x0000 -+ -+/* Standard BIOS video modes (BIOS number + 0x0100) */ -+#define VIDEO_FIRST_BIOS 0x0100 -+ -+/* VESA BIOS video modes (VESA number + 0x0200) */ -+#define VIDEO_FIRST_VESA 0x0200 -+ -+/* Video7 special modes (BIOS number + 0x0900) */ -+#define VIDEO_FIRST_V7 0x0900 -+ -+/* Special video modes */ -+#define VIDEO_FIRST_SPECIAL 0x0f00 -+#define VIDEO_80x25 0x0f00 -+#define VIDEO_8POINT 0x0f01 -+#define VIDEO_80x43 0x0f02 -+#define VIDEO_80x28 0x0f03 -+#define VIDEO_CURRENT_MODE 0x0f04 -+#define VIDEO_80x30 0x0f05 -+#define VIDEO_80x34 0x0f06 -+#define VIDEO_80x60 0x0f07 -+#define VIDEO_GFX_HACK 0x0f08 -+#define VIDEO_LAST_SPECIAL 0x0f09 -+ -+/* Video modes given by resolution */ -+#define VIDEO_FIRST_RESOLUTION 0x1000 -+ -+/* The "recalculate timings" flag */ -+#define VIDEO_RECALC 0x8000 -+ -+/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ -+#ifdef CONFIG_VIDEO_RETAIN -+void store_screen(void); -+#define DO_STORE() store_screen() -+#else -+#define DO_STORE() ((void)0) -+#endif /* CONFIG_VIDEO_RETAIN */ -+ -+/* -+ * Mode table structures -+ */ -+ -+struct mode_info { -+ u16 mode; /* Mode number (vga= style) */ -+ u8 x, y; /* Width, height */ -+}; -+ -+struct card_info { -+ const char *card_name; -+ int (*set_mode)(struct mode_info *mode); -+ int (*probe)(void); -+ struct mode_info *modes; -+ int nmodes; /* Number of probed modes so far */ -+ int unsafe; /* Probing is unsafe, only do after "scan" */ -+ u16 xmode_first; /* Unprobed modes to try to call anyway */ -+ u16 xmode_n; /* Size of unprobed mode range */ -+}; -+ -+#define __videocard struct card_info __attribute__((section(".videocards"))) -+extern struct card_info video_cards[], video_cards_end[]; -+ -+int mode_defined(u16 mode); /* video.c */ -+ -+/* Basic video information */ -+#define ADAPTER_CGA 0 /* CGA/MDA/HGC */ -+#define ADAPTER_EGA 1 -+#define ADAPTER_VGA 2 -+ -+extern int adapter; -+extern u16 video_segment; -+extern int force_x, force_y; /* Don't query the BIOS for cols/rows */ -+extern int do_restore; /* Restore screen contents */ -+extern int graphic_mode; /* Graphics mode with linear frame buffer */ -+ -+/* -+ * int $0x10 is notorious for touching registers it shouldn't. -+ * gcc doesn't like %ebp being clobbered, so define it as a push/pop -+ * sequence here. -+ */ -+#define INT10 "pushl %%ebp; int $0x10; popl %%ebp" -+ -+/* Accessing VGA indexed registers */ -+static inline u8 in_idx(u16 port, u8 index) -+{ -+ outb(index, port); -+ return inb(port+1); -+} -+ -+static inline void out_idx(u8 v, u16 port, u8 index) -+{ -+ outw(index+(v << 8), port); -+} -+ -+/* Writes a value to an indexed port and then reads the port again */ -+static inline u8 tst_idx(u8 v, u16 port, u8 index) -+{ -+ out_idx(port, index, v); -+ return in_idx(port, index); -+} -+ -+/* Get the I/O port of the VGA CRTC */ -+u16 vga_crtc(void); /* video-vga.c */ -+ -+#endif /* BOOT_VIDEO_H */ ---- /dev/null -+++ b/arch/i386/boot/voyager.c -@@ -0,0 +1,46 @@ -+/* -*- 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. -+ * -+ * ----------------------------------------------------------------------- */ -+ -+/* -+ * arch/i386/boot/voyager.c -+ * -+ * Get the Voyager config information -+ */ -+ -+#include "boot.h" -+ -+#ifdef CONFIG_X86_VOYAGER -+ -+int query_voyager(void) -+{ -+ u8 err; -+ u16 es, di; -+ /* Abuse the apm_bios_info area for this */ -+ u8 *data_ptr = (u8 *)&boot_params.apm_bios_info; -+ -+ data_ptr[0] = 0xff; /* Flag on config not found(?) */ -+ -+ asm("pushw %%es ; " -+ "int $0x15 ; " -+ "setc %0 ; " -+ "movw %%es, %1 ; " -+ "popw %%es" -+ : "=qm" (err), "=rm" (es), "=D" (di) -+ : "a" (0xffc0)); -+ -+ if (err) -+ return -1; /* Not Voyager */ -+ -+ set_fs(es); -+ copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */ -+ return 0; -+} -+ -+#endif /* CONFIG_X86_VOYAGER */ ---- /dev/null -+++ b/arch/i386/kernel/cpu/addon_cpuid_features.c -@@ -0,0 +1,50 @@ -+ -+/* -+ * Routines to indentify additional cpu features that are scattered in -+ * cpuid space. -+ */ -+ -+#include -+ -+#include -+ -+struct cpuid_bit { -+ u16 feature; -+ u8 reg; -+ u8 bit; -+ u32 level; -+}; -+ -+enum cpuid_regs { -+ CR_EAX = 0, -+ CR_ECX, -+ CR_EDX, -+ CR_EBX -+}; -+ -+void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) -+{ -+ u32 max_level; -+ u32 regs[4]; -+ const struct cpuid_bit *cb; -+ -+ static const struct cpuid_bit cpuid_bits[] = { -+ { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, -+ { 0, 0, 0, 0 } -+ }; -+ -+ for (cb = cpuid_bits; cb->feature; cb++) { -+ -+ /* Verify that the level is valid */ -+ max_level = cpuid_eax(cb->level & 0xffff0000); -+ if (max_level < cb->level || -+ max_level > (cb->level | 0xffff)) -+ continue; -+ -+ cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX], -+ ®s[CR_ECX], ®s[CR_EDX]); -+ -+ if (regs[cb->reg] & (1 << cb->bit)) -+ set_bit(cb->feature, c->x86_capability); -+ } -+} ---- a/arch/i386/kernel/cpu/common.c -+++ b/arch/i386/kernel/cpu/common.c -@@ -353,6 +353,8 @@ - if ( xlvl >= 0x80000004 ) - get_model_name(c); /* Default name */ - } -+ -+ init_scattered_cpuid_features(c); - } - - early_intel_workaround(c); ---- a/arch/i386/kernel/cpu/proc.c -+++ b/arch/i386/kernel/cpu/proc.c -@@ -29,7 +29,8 @@ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, -- NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", -+ NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", -+ "3dnowext", "3dnow", - - /* Transmeta-defined */ - "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, -@@ -40,8 +41,9 @@ - /* Other (Linux-defined) */ - "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", - NULL, NULL, NULL, NULL, -- "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, -- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ "constant_tsc", "up", NULL, "arch_perfmon", -+ "pebs", "bts", NULL, "sync_rdtsc", -+ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Intel-defined (#2) */ -@@ -57,9 +59,16 @@ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* AMD-defined (#2) */ -- "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm", -- "sse4a", "misalignsse", -- "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, -+ "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", -+ "altmovcr8", "abm", "sse4a", -+ "misalignsse", "3dnowprefetch", -+ "osvw", "ibs", NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ -+ /* Auxiliary (Linux-defined) */ -+ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - }; ---- a/arch/i386/kernel/e820.c -+++ b/arch/i386/kernel/e820.c -@@ -734,7 +734,7 @@ - case E820_NVS: - printk("(ACPI NVS)\n"); - break; -- default: printk("type %lu\n", e820.map[i].type); -+ default: printk("type %u\n", e820.map[i].type); - break; - } - } ---- a/arch/i386/kernel/setup.c -+++ b/arch/i386/kernel/setup.c -@@ -102,19 +102,10 @@ - /* - * Setup options - */ --struct drive_info_struct { char dummy[32]; } drive_info; --#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \ -- defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) --EXPORT_SYMBOL(drive_info); --#endif - struct screen_info screen_info; - EXPORT_SYMBOL(screen_info); - struct apm_info apm_info; - EXPORT_SYMBOL(apm_info); --struct sys_desc_table_struct { -- unsigned short length; -- unsigned char table[0]; --}; - struct edid_info edid_info; - EXPORT_SYMBOL_GPL(edid_info); - struct ist_info ist_info; -@@ -134,7 +125,7 @@ - - static char __initdata command_line[COMMAND_LINE_SIZE]; - --unsigned char __initdata boot_params[PARAM_SIZE]; -+struct boot_params __initdata boot_params; - - #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) - struct edd edd; -@@ -528,7 +519,6 @@ - #endif - - ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); -- drive_info = DRIVE_INFO; - screen_info = SCREEN_INFO; - edid_info = EDID_INFO; - apm_info.bios = APM_BIOS_INFO; ---- a/arch/i386/kernel/verify_cpu.S -+++ /dev/null -@@ -1,94 +0,0 @@ --/* Check if CPU has some minimum CPUID bits -- This runs in 16bit mode so that the caller can still use the BIOS -- to output errors on the screen */ --#include --#include -- --verify_cpu: -- pushfl # Save caller passed flags -- pushl $0 # Kill any dangerous flags -- popfl -- --#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 -- pushfl -- pop %eax -- orl $(1<<18),%eax # try setting AC -- push %eax -- popfl -- pushfl -- popl %eax -- testl $(1<<18),%eax -- jz bad --#endif --#if REQUIRED_MASK1 != 0 -- pushfl # standard way to check for cpuid -- popl %eax -- movl %eax,%ebx -- xorl $0x200000,%eax -- pushl %eax -- popfl -- pushfl -- popl %eax -- cmpl %eax,%ebx -- pushfl # standard way to check for cpuid -- popl %eax -- movl %eax,%ebx -- xorl $0x200000,%eax -- pushl %eax -- popfl -- pushfl -- popl %eax -- cmpl %eax,%ebx -- jz bad # REQUIRED_MASK1 != 0 requires CPUID -- -- movl $0x0,%eax # See if cpuid 1 is implemented -- cpuid -- cmpl $0x1,%eax -- jb bad # no cpuid 1 -- --#if REQUIRED_MASK1 & NEED_CMPXCHG64 -- /* Some VIA C3s need magic MSRs to enable CX64. Do this here */ -- cmpl $0x746e6543,%ebx # Cent -- jne 1f -- cmpl $0x48727561,%edx # aurH -- jne 1f -- cmpl $0x736c7561,%ecx # auls -- jne 1f -- movl $1,%eax # check model -- cpuid -- movl %eax,%ebx -- shr $8,%ebx -- andl $0xf,%ebx -- cmp $6,%ebx # check family == 6 -- jne 1f -- shr $4,%eax -- andl $0xf,%eax -- cmpl $6,%eax # check model >= 6 -- jb 1f -- # assume models >= 6 all support this MSR -- movl $MSR_VIA_FCR,%ecx -- rdmsr -- orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE -- wrmsr --1: --#endif -- movl $0x1,%eax # Does the cpu have what it takes -- cpuid -- --#if CONFIG_X86_MINIMUM_CPU_MODEL > 4 --#error add proper model checking here --#endif -- -- andl $REQUIRED_MASK1,%edx -- xorl $REQUIRED_MASK1,%edx -- jnz bad --#endif /* REQUIRED_MASK1 */ -- -- popfl -- xor %eax,%eax -- ret -- --bad: -- popfl -- movl $1,%eax -- ret ---- a/arch/x86_64/Kconfig -+++ b/arch/x86_64/Kconfig -@@ -427,6 +427,10 @@ - This is purely to save memory - each supported CPU requires - memory in the static kernel configuration. - -+config PHYSICAL_ALIGN -+ hex -+ default "0x200000" -+ - config HOTPLUG_CPU - bool "Support for suspend on SMP and hot-pluggable CPUs (EXPERIMENTAL)" - depends on SMP && HOTPLUG && EXPERIMENTAL ---- a/arch/x86_64/boot/Makefile -+++ b/arch/x86_64/boot/Makefile -@@ -1,135 +1,9 @@ - # - # arch/x86_64/boot/Makefile - # --# This file is subject to the terms and conditions of the GNU General Public --# License. See the file "COPYING" in the main directory of this archive --# for more details. --# --# Copyright (C) 1994 by Linus Torvalds --# -- --# ROOT_DEV specifies the default root-device when making the image. --# This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case --# the default of FLOPPY is used by 'build'. -- --ROOT_DEV := CURRENT -- --# If you want to preset the SVGA mode, uncomment the next line and --# set SVGA_MODE to whatever number you want. --# Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode. --# The number is the same as you would ordinarily press at bootup. -- --SVGA_MODE := -DSVGA_MODE=NORMAL_VGA -- --# If you want the RAM disk device, define this to be the size in blocks. -- --#RAMDISK := -DRAMDISK=512 -- --targets := vmlinux.bin bootsect bootsect.o \ -- setup setup.o bzImage mtools.conf -- --EXTRA_CFLAGS := -m32 -- --hostprogs-y := tools/build --HOST_EXTRACFLAGS += $(LINUXINCLUDE) --subdir- := compressed/ #Let make clean descend in compressed/ --# --------------------------------------------------------------------------- -- --$(obj)/bzImage: IMAGE_OFFSET := 0x100000 --$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ --$(obj)/bzImage: BUILDFLAGS := -b -- --quiet_cmd_image = BUILD $@ --cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ -- $(obj)/vmlinux.bin $(ROOT_DEV) > $@ -- --$(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ -- $(obj)/vmlinux.bin $(obj)/tools/build FORCE -- $(call if_changed,image) -- @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' -- --$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE -- $(call if_changed,objcopy) -- --LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary --LDFLAGS_setup := -Ttext 0x0 -s --oformat binary -e begtext -- --$(obj)/setup $(obj)/bootsect: %: %.o FORCE -- $(call if_changed,ld) -- --$(obj)/compressed/vmlinux: FORCE -- $(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@ -- --# Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel --FDARGS = --# Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel --FDINITRD = -- --image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,) -- --$(obj)/mtools.conf: $(src)/mtools.conf.in -- sed -e 's|@OBJ@|$(obj)|g' < $< > $@ -- --# This requires write access to /dev/fd0 --zdisk: $(BOOTIMAGE) $(obj)/mtools.conf -- MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync -- syslinux /dev/fd0 ; sync -- echo '$(image_cmdline)' | \ -- MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg -- if [ -f '$(FDINITRD)' ] ; then \ -- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' a:initrd.img ; \ -- fi -- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync -- --# These require being root or having syslinux 2.02 or higher installed --fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf -- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 -- MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync -- syslinux $(obj)/fdimage ; sync -- echo '$(image_cmdline)' | \ -- MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg -- if [ -f '$(FDINITRD)' ] ; then \ -- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' v:initrd.img ; \ -- fi -- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync -- --fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf -- dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 -- MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync -- syslinux $(obj)/fdimage ; sync -- echo '$(image_cmdline)' | \ -- MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg -- if [ -f '$(FDINITRD)' ] ; then \ -- MTOOLSRC=$(obj)/mtools.conf mcopy '$(FDINITRD)' w:initrd.img ; \ -- fi -- MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync -- --isoimage: $(BOOTIMAGE) -- -rm -rf $(obj)/isoimage -- mkdir $(obj)/isoimage -- for i in lib lib64 share end ; do \ -- if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \ -- cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \ -- break ; \ -- fi ; \ -- if [ $$i = end ] ; then exit 1 ; fi ; \ -- done -- cp $(BOOTIMAGE) $(obj)/isoimage/linux -- echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg -- if [ -f '$(FDINITRD)' ] ; then \ -- cp '$(FDINITRD)' $(obj)/isoimage/initrd.img ; \ -- fi -- mkisofs -J -r -o $(obj)/image.iso -b isolinux.bin -c boot.cat \ -- -no-emul-boot -boot-load-size 4 -boot-info-table \ -- $(obj)/isoimage -- rm -rf $(obj)/isoimage -- --zlilo: $(BOOTIMAGE) -- if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi -- if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi -- cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz -- cp System.map $(INSTALL_PATH)/ -- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi -+# The actual boot code is shared with i386 including the Makefile. -+# So tell kbuild that we fetch the code from i386 and include the -+# Makefile from i386 too. - --install: -- sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(BOOTIMAGE) System.map "$(INSTALL_PATH)" -+src := arch/i386/boot -+include $(src)/Makefile ---- a/arch/x86_64/boot/bootsect.S -+++ /dev/null -@@ -1,98 +0,0 @@ --/* -- * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds -- * -- * modified by Drew Eckhardt -- * modified by Bruce Evans (bde) -- * modified by Chris Noe (May 1999) (as86 -> gas) -- * gutted by H. Peter Anvin (Jan 2003) -- * -- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment -- * addresses must be multiplied by 16 to obtain their respective linear -- * addresses. To avoid confusion, linear addresses are written using leading -- * hex while segment addresses are written as segment:offset. -- * -- */ -- --#include -- --SETUPSECTS = 4 /* default nr of setup-sectors */ --BOOTSEG = 0x07C0 /* original address of boot-sector */ --INITSEG = DEF_INITSEG /* we move boot here - out of the way */ --SETUPSEG = DEF_SETUPSEG /* setup starts here */ --SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ --SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ -- /* to be loaded */ --ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ --SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ -- --#ifndef SVGA_MODE --#define SVGA_MODE ASK_VGA --#endif -- --#ifndef RAMDISK --#define RAMDISK 0 --#endif -- --#ifndef ROOT_RDONLY --#define ROOT_RDONLY 1 --#endif -- --.code16 --.text -- --.global _start --_start: -- -- # Normalize the start address -- jmpl $BOOTSEG, $start2 -- --start2: -- movw %cs, %ax -- movw %ax, %ds -- movw %ax, %es -- movw %ax, %ss -- movw $0x7c00, %sp -- sti -- cld -- -- movw $bugger_off_msg, %si -- --msg_loop: -- lodsb -- andb %al, %al -- jz die -- movb $0xe, %ah -- movw $7, %bx -- int $0x10 -- jmp msg_loop -- --die: -- # Allow the user to press a key, then reboot -- xorw %ax, %ax -- int $0x16 -- int $0x19 -- -- # int 0x19 should never return. In case it does anyway, -- # invoke the BIOS reset code... -- ljmp $0xf000,$0xfff0 -- -- --bugger_off_msg: -- .ascii "Direct booting from floppy is no longer supported.\r\n" -- .ascii "Please use a boot loader program instead.\r\n" -- .ascii "\n" -- .ascii "Remove disk and press any key to reboot . . .\r\n" -- .byte 0 -- -- -- # Kernel attributes; used by setup -- -- .org 497 --setup_sects: .byte SETUPSECTS --root_flags: .word ROOT_RDONLY --syssize: .word SYSSIZE --swap_dev: .word SWAP_DEV --ram_size: .word RAMDISK --vid_mode: .word SVGA_MODE --root_dev: .word ROOT_DEV --boot_flag: .word 0xAA55 ---- a/arch/x86_64/boot/compressed/Makefile -+++ b/arch/x86_64/boot/compressed/Makefile -@@ -7,11 +7,12 @@ - # - - targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o --EXTRA_AFLAGS := -traditional - --# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with --# -m32 --CFLAGS := -m64 -D__KERNEL__ -Iinclude -O2 -fno-strict-aliasing -fPIC -mcmodel=small -fno-builtin -+CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2 \ -+ -fno-strict-aliasing -fPIC -mcmodel=small \ -+ $(call cc-option, -ffreestanding) \ -+ $(call cc-option, -fno-stack-protector) -+AFLAGS := $(CFLAGS) -D__ASSEMBLY__ - LDFLAGS := -m elf_x86_64 - - LDFLAGS_vmlinux := -T ---- a/arch/x86_64/boot/compressed/head.S -+++ b/arch/x86_64/boot/compressed/head.S -@@ -46,10 +46,10 @@ - * at and where we were actually loaded at. This can only be done - * with a short local call on x86. Nothing else will tell us what - * address we are running at. The reserved chunk of the real-mode -- * data at 0x34-0x3f are used as the stack for this calculation. -- * Only 4 bytes are needed. -+ * data at 0x1e4 (defined as a scratch field) are used as the stack -+ * for this calculation. Only 4 bytes are needed. - */ -- leal 0x40(%esi), %esp -+ leal (0x1e4+4)(%esi), %esp - call 1f - 1: popl %ebp - subl $1b, %ebp ---- a/arch/x86_64/boot/install.sh -+++ /dev/null -@@ -1,2 +0,0 @@ --#!/bin/sh --. $srctree/arch/i386/boot/install.sh ---- a/arch/x86_64/boot/mtools.conf.in -+++ /dev/null -@@ -1,17 +0,0 @@ --# --# mtools configuration file for "make (b)zdisk" --# -- --# Actual floppy drive --drive a: -- file="/dev/fd0" -- --# 1.44 MB floppy disk image --drive v: -- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter -- --# 2.88 MB floppy disk image (mostly for virtual uses) --drive w: -- file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter -- -- ---- a/arch/x86_64/boot/setup.S -+++ /dev/null -@@ -1,826 +0,0 @@ --/* -- * setup.S Copyright (C) 1991, 1992 Linus Torvalds -- * -- * setup.s is responsible for getting the system data from the BIOS, -- * and putting them into the appropriate places in system memory. -- * both setup.s and system has been loaded by the bootblock. -- * -- * This code asks the bios for memory/disk/other parameters, and -- * puts them in a "safe" place: 0x90000-0x901FF, ie where the -- * boot-block used to be. It is then up to the protected mode -- * system to read them from there before the area is overwritten -- * for buffer-blocks. -- * -- * Move PS/2 aux init code to psaux.c -- * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 -- * -- * some changes and additional features by Christoph Niemann, -- * March 1993/June 1994 (Christoph.Niemann@linux.org) -- * -- * add APM BIOS checking by Stephen Rothwell, May 1994 -- * (sfr@canb.auug.org.au) -- * -- * High load stuff, initrd support and position independency -- * by Hans Lermen & Werner Almesberger, February 1996 -- * , -- * -- * Video handling moved to video.S by Martin Mares, March 1996 -- * -- * -- * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david -- * parsons) to avoid loadlin confusion, July 1997 -- * -- * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. -- * -- * -- * Fix to work around buggy BIOSes which don't use carry bit correctly -- * and/or report extended memory in CX/DX for e801h memory size detection -- * call. As a result the kernel got wrong figures. The int15/e801h docs -- * from Ralf Brown interrupt list seem to indicate AX/BX should be used -- * anyway. So to avoid breaking many machines (presumably there was a reason -- * to orginally use CX/DX instead of AX/BX), we do a kludge to see -- * if CX/DX have been changed in the e801 call and if so use AX/BX . -- * Michael Miller, April 2001 -- * -- * Added long mode checking and SSE force. March 2003, Andi Kleen. -- */ -- --#include --#include --#include --#include --#include --#include --#include -- --/* Signature words to ensure LILO loaded us right */ --#define SIG1 0xAA55 --#define SIG2 0x5A5A -- --INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way --SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). --SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment -- # ... and the former contents of CS -- --DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 -- --.code16 --.globl begtext, begdata, begbss, endtext, enddata, endbss -- --.text --begtext: --.data --begdata: --.bss --begbss: --.text -- --start: -- jmp trampoline -- --# This is the setup header, and it must start at %cs:2 (old 0x9020:2) -- -- .ascii "HdrS" # header signature -- .word 0x0206 # header version number (>= 0x0105) -- # or else old loadlin-1.5 will fail) --realmode_swtch: .word 0, 0 # default_switch, SETUPSEG --start_sys_seg: .word SYSSEG -- .word kernel_version # pointing to kernel version string -- # above section of header is compatible -- # with loadlin-1.5 (header v1.5). Don't -- # change it. -- --type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, -- # Bootlin, SYSLX, bootsect...) -- # See Documentation/i386/boot.txt for -- # assigned ids -- --# flags, unused bits must be zero (RFU) bit within loadflags --loadflags: --LOADED_HIGH = 1 # If set, the kernel is loaded high --CAN_USE_HEAP = 0x80 # If set, the loader also has set -- # heap_end_ptr to tell how much -- # space behind setup.S can be used for -- # heap purposes. -- # Only the loader knows what is free --#ifndef __BIG_KERNEL__ -- .byte 0 --#else -- .byte LOADED_HIGH --#endif -- --setup_move_size: .word 0x8000 # size to move, when setup is not -- # loaded at 0x90000. We will move setup -- # to 0x90000 then just before jumping -- # into the kernel. However, only the -- # loader knows how much data behind -- # us also needs to be loaded. -- --code32_start: # here loaders can put a different -- # start address for 32-bit code. --#ifndef __BIG_KERNEL__ -- .long 0x1000 # 0x1000 = default for zImage --#else -- .long 0x100000 # 0x100000 = default for big kernel --#endif -- --ramdisk_image: .long 0 # address of loaded ramdisk image -- # Here the loader puts the 32-bit -- # address where it loaded the image. -- # This only will be read by the kernel. -- --ramdisk_size: .long 0 # its size in bytes -- --bootsect_kludge: -- .long 0 # obsolete -- --heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) -- # space from here (exclusive) down to -- # end of setup code can be used by setup -- # for local heap purposes. -- --pad1: .word 0 --cmd_line_ptr: .long 0 # (Header version 0x0202 or later) -- # If nonzero, a 32-bit pointer -- # to the kernel command line. -- # The command line should be -- # located between the start of -- # setup and the end of low -- # memory (0xa0000), or it may -- # get overwritten before it -- # gets read. If this field is -- # used, there is no longer -- # anything magical about the -- # 0x90000 segment; the setup -- # can be located anywhere in -- # low memory 0x10000 or higher. -- --ramdisk_max: .long 0xffffffff --kernel_alignment: .long 0x200000 # physical addr alignment required for -- # protected mode relocatable kernel --#ifdef CONFIG_RELOCATABLE --relocatable_kernel: .byte 1 --#else --relocatable_kernel: .byte 0 --#endif --pad2: .byte 0 --pad3: .word 0 -- --cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, -- #added with boot protocol -- #version 2.06 -- --trampoline: call start_of_setup -- .align 16 -- # The offset at this point is 0x240 -- .space (0xeff-0x240+1) # E820 & EDD space (ending at 0xeff) --# End of setup header ##################################################### -- --start_of_setup: --# Bootlin depends on this being done early -- movw $0x01500, %ax -- movb $0x81, %dl -- int $0x13 -- --#ifdef SAFE_RESET_DISK_CONTROLLER --# Reset the disk controller. -- movw $0x0000, %ax -- movb $0x80, %dl -- int $0x13 --#endif -- --# Set %ds = %cs, we know that SETUPSEG = %cs at this point -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds --# Check signature at end of setup -- cmpw $SIG1, setup_sig1 -- jne bad_sig -- -- cmpw $SIG2, setup_sig2 -- jne bad_sig -- -- jmp good_sig1 -- --# Routine to print asciiz string at ds:si --prtstr: -- lodsb -- andb %al, %al -- jz fin -- -- call prtchr -- jmp prtstr -- --fin: ret -- --# Space printing --prtsp2: call prtspc # Print double space --prtspc: movb $0x20, %al # Print single space (note: fall-thru) -- --prtchr: -- pushw %ax -- pushw %cx -- movw $0007,%bx -- movw $0x01, %cx -- movb $0x0e, %ah -- int $0x10 -- popw %cx -- popw %ax -- ret -- --beep: movb $0x07, %al -- jmp prtchr -- --no_sig_mess: .string "No setup signature found ..." -- --good_sig1: -- jmp good_sig -- --# We now have to find the rest of the setup code/data --bad_sig: -- movw %cs, %ax # SETUPSEG -- subw $DELTA_INITSEG, %ax # INITSEG -- movw %ax, %ds -- xorb %bh, %bh -- movb (497), %bl # get setup sect from bootsect -- subw $4, %bx # LILO loads 4 sectors of setup -- shlw $8, %bx # convert to words (1sect=2^8 words) -- movw %bx, %cx -- shrw $3, %bx # convert to segment -- addw $SYSSEG, %bx -- movw %bx, %cs:start_sys_seg --# Move rest of setup code/data to here -- movw $2048, %di # four sectors loaded by LILO -- subw %si, %si -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %es -- movw $SYSSEG, %ax -- movw %ax, %ds -- rep -- movsw -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds -- cmpw $SIG1, setup_sig1 -- jne no_sig -- -- cmpw $SIG2, setup_sig2 -- jne no_sig -- -- jmp good_sig -- --no_sig: -- lea no_sig_mess, %si -- call prtstr -- --no_sig_loop: -- jmp no_sig_loop -- --good_sig: -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %ds --# Check if an old loader tries to load a big-kernel -- testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? -- jz loader_ok # No, no danger for old loaders. -- -- cmpb $0, %cs:type_of_loader # Do we have a loader that -- # can deal with us? -- jnz loader_ok # Yes, continue. -- -- pushw %cs # No, we have an old loader, -- popw %ds # die. -- lea loader_panic_mess, %si -- call prtstr -- -- jmp no_sig_loop -- --loader_panic_mess: .string "Wrong loader, giving up..." -- --loader_ok: -- /* check for long mode. */ -- /* we have to do this before the VESA setup, otherwise the user -- can't see the error message. */ -- -- pushw %ds -- movw %cs,%ax -- movw %ax,%ds -- -- call verify_cpu -- testl %eax,%eax -- jz sse_ok -- --no_longmode: -- call beep -- lea long_mode_panic,%si -- call prtstr --no_longmode_loop: -- jmp no_longmode_loop --long_mode_panic: -- .string "Your CPU does not support long mode. Use a 32bit distribution." -- .byte 0 -- --#include "../kernel/verify_cpu.S" --sse_ok: -- popw %ds -- --# tell BIOS we want to go to long mode -- movl $0xec00,%eax # declare target operating mode -- movl $2,%ebx # long mode -- int $0x15 -- --# Get memory size (extended mem, kB) -- -- xorl %eax, %eax -- movl %eax, (0x1e0) --#ifndef STANDARD_MEMORY_BIOS_CALL -- movb %al, (E820NR) --# Try three different memory detection schemes. First, try --# e820h, which lets us assemble a memory map, then try e801h, --# which returns a 32-bit memory size, and finally 88h, which --# returns 0-64m -- --# method E820H: --# the memory map from hell. e820h returns memory classified into --# a whole bunch of different types, and allows memory holes and --# everything. We scan through this memory map and build a list --# of the first 32 memory areas, which we return at [E820MAP]. --# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. -- --#define SMAP 0x534d4150 -- --meme820: -- xorl %ebx, %ebx # continuation counter -- movw $E820MAP, %di # point into the whitelist -- # so we can have the bios -- # directly write into it. -- --jmpe820: -- movl $0x0000e820, %eax # e820, upper word zeroed -- movl $SMAP, %edx # ascii 'SMAP' -- movl $20, %ecx # size of the e820rec -- pushw %ds # data record. -- popw %es -- int $0x15 # make the call -- jc bail820 # fall to e801 if it fails -- -- cmpl $SMAP, %eax # check the return is `SMAP' -- jne bail820 # fall to e801 if it fails -- --# cmpl $1, 16(%di) # is this usable memory? --# jne again820 -- -- # If this is usable memory, we save it by simply advancing %di by -- # sizeof(e820rec). -- # --good820: -- movb (E820NR), %al # up to 128 entries -- cmpb $E820MAX, %al -- jae bail820 -- -- incb (E820NR) -- movw %di, %ax -- addw $20, %ax -- movw %ax, %di --again820: -- cmpl $0, %ebx # check to see if -- jne jmpe820 # %ebx is set to EOF --bail820: -- -- --# method E801H: --# memory size is in 1k chunksizes, to avoid confusing loadlin. --# we store the 0xe801 memory size in a completely different place, --# because it will most likely be longer than 16 bits. --# (use 1e0 because that's what Larry Augustine uses in his --# alternative new memory detection scheme, and it's sensible --# to write everything into the same place.) -- --meme801: -- stc # fix to work around buggy -- xorw %cx,%cx # BIOSes which don't clear/set -- xorw %dx,%dx # carry on pass/error of -- # e801h memory size call -- # or merely pass cx,dx though -- # without changing them. -- movw $0xe801, %ax -- int $0x15 -- jc mem88 -- -- cmpw $0x0, %cx # Kludge to handle BIOSes -- jne e801usecxdx # which report their extended -- cmpw $0x0, %dx # memory in AX/BX rather than -- jne e801usecxdx # CX/DX. The spec I have read -- movw %ax, %cx # seems to indicate AX/BX -- movw %bx, %dx # are more reasonable anyway... -- --e801usecxdx: -- andl $0xffff, %edx # clear sign extend -- shll $6, %edx # and go from 64k to 1k chunks -- movl %edx, (0x1e0) # store extended memory size -- andl $0xffff, %ecx # clear sign extend -- addl %ecx, (0x1e0) # and add lower memory into -- # total size. -- --# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or --# 64mb, depending on the bios) in ax. --mem88: -- --#endif -- movb $0x88, %ah -- int $0x15 -- movw %ax, (2) -- --# Set the keyboard repeat rate to the max -- movw $0x0305, %ax -- xorw %bx, %bx -- int $0x16 -- --# Check for video adapter and its parameters and allow the --# user to browse video modes. -- call video # NOTE: we need %ds pointing -- # to bootsector -- --# Get hd0 data... -- xorw %ax, %ax -- movw %ax, %ds -- ldsw (4 * 0x41), %si -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- pushw %ax -- movw %ax, %es -- movw $0x0080, %di -- movw $0x10, %cx -- pushw %cx -- cld -- rep -- movsb --# Get hd1 data... -- xorw %ax, %ax -- movw %ax, %ds -- ldsw (4 * 0x46), %si -- popw %cx -- popw %es -- movw $0x0090, %di -- rep -- movsb --# Check that there IS a hd1 :-) -- movw $0x01500, %ax -- movb $0x81, %dl -- int $0x13 -- jc no_disk1 -- -- cmpb $3, %ah -- je is_disk1 -- --no_disk1: -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %es -- movw $0x0090, %di -- movw $0x10, %cx -- xorw %ax, %ax -- cld -- rep -- stosb --is_disk1: -- --# Check for PS/2 pointing device -- movw %cs, %ax # aka SETUPSEG -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ax, %ds -- movb $0, (0x1ff) # default is no pointing device -- int $0x11 # int 0x11: equipment list -- testb $0x04, %al # check if mouse installed -- jz no_psmouse -- -- movb $0xAA, (0x1ff) # device present --no_psmouse: -- --#include "../../i386/boot/edd.S" -- --# Now we want to move to protected mode ... -- cmpw $0, %cs:realmode_swtch -- jz rmodeswtch_normal -- -- lcall *%cs:realmode_swtch -- -- jmp rmodeswtch_end -- --rmodeswtch_normal: -- pushw %cs -- call default_switch -- --rmodeswtch_end: --# we get the code32 start address and modify the below 'jmpi' --# (loader may have changed it) -- movl %cs:code32_start, %eax -- movl %eax, %cs:code32 -- --# Now we move the system to its rightful place ... but we check if we have a --# big-kernel. In that case we *must* not move it ... -- testb $LOADED_HIGH, %cs:loadflags -- jz do_move0 # .. then we have a normal low -- # loaded zImage -- # .. or else we have a high -- # loaded bzImage -- jmp end_move # ... and we skip moving -- --do_move0: -- movw $0x100, %ax # start of destination segment -- movw %cs, %bp # aka SETUPSEG -- subw $DELTA_INITSEG, %bp # aka INITSEG -- movw %cs:start_sys_seg, %bx # start of source segment -- cld --do_move: -- movw %ax, %es # destination segment -- incb %ah # instead of add ax,#0x100 -- movw %bx, %ds # source segment -- addw $0x100, %bx -- subw %di, %di -- subw %si, %si -- movw $0x800, %cx -- rep -- movsw -- cmpw %bp, %bx # assume start_sys_seg > 0x200, -- # so we will perhaps read one -- # page more than needed, but -- # never overwrite INITSEG -- # because destination is a -- # minimum one page below source -- jb do_move -- --end_move: --# then we load the segment descriptors -- movw %cs, %ax # aka SETUPSEG -- movw %ax, %ds -- --# Check whether we need to be downward compatible with version <=201 -- cmpl $0, cmd_line_ptr -- jne end_move_self # loader uses version >=202 features -- cmpb $0x20, type_of_loader -- je end_move_self # bootsect loader, we know of it -- --# Boot loader doesnt support boot protocol version 2.02. --# If we have our code not at 0x90000, we need to move it there now. --# We also then need to move the params behind it (commandline) --# Because we would overwrite the code on the current IP, we move --# it in two steps, jumping high after the first one. -- movw %cs, %ax -- cmpw $SETUPSEG, %ax -- je end_move_self -- -- cli # make sure we really have -- # interrupts disabled ! -- # because after this the stack -- # should not be used -- subw $DELTA_INITSEG, %ax # aka INITSEG -- movw %ss, %dx -- cmpw %ax, %dx -- jb move_self_1 -- -- addw $INITSEG, %dx -- subw %ax, %dx # this will go into %ss after -- # the move --move_self_1: -- movw %ax, %ds -- movw $INITSEG, %ax # real INITSEG -- movw %ax, %es -- movw %cs:setup_move_size, %cx -- std # we have to move up, so we use -- # direction down because the -- # areas may overlap -- movw %cx, %di -- decw %di -- movw %di, %si -- subw $move_self_here+0x200, %cx -- rep -- movsb -- ljmp $SETUPSEG, $move_self_here -- --move_self_here: -- movw $move_self_here+0x200, %cx -- rep -- movsb -- movw $SETUPSEG, %ax -- movw %ax, %ds -- movw %dx, %ss --end_move_self: # now we are at the right place -- lidt idt_48 # load idt with 0,0 -- xorl %eax, %eax # Compute gdt_base -- movw %ds, %ax # (Convert %ds:gdt to a linear ptr) -- shll $4, %eax -- addl $gdt, %eax -- movl %eax, (gdt_48+2) -- lgdt gdt_48 # load gdt with whatever is -- # appropriate -- --# that was painless, now we enable a20 -- call empty_8042 -- -- movb $0xD1, %al # command write -- outb %al, $0x64 -- call empty_8042 -- -- movb $0xDF, %al # A20 on -- outb %al, $0x60 -- call empty_8042 -- --# --# You must preserve the other bits here. Otherwise embarrasing things --# like laptops powering off on boot happen. Corrected version by Kira --# Brown from Linux 2.2 --# -- inb $0x92, %al # -- orb $02, %al # "fast A20" version -- outb %al, $0x92 # some chips have only this -- --# wait until a20 really *is* enabled; it can take a fair amount of --# time on certain systems; Toshiba Tecras are known to have this --# problem. The memory location used here (0x200) is the int 0x80 --# vector, which should be safe to use. -- -- xorw %ax, %ax # segment 0x0000 -- movw %ax, %fs -- decw %ax # segment 0xffff (HMA) -- movw %ax, %gs --a20_wait: -- incw %ax # unused memory location <0xfff0 -- movw %ax, %fs:(0x200) # we use the "int 0x80" vector -- cmpw %gs:(0x210), %ax # and its corresponding HMA addr -- je a20_wait # loop until no longer aliased -- --# make sure any possible coprocessor is properly reset.. -- xorw %ax, %ax -- outb %al, $0xf0 -- call delay -- -- outb %al, $0xf1 -- call delay -- --# well, that went ok, I hope. Now we mask all interrupts - the rest --# is done in init_IRQ(). -- movb $0xFF, %al # mask all interrupts for now -- outb %al, $0xA1 -- call delay -- -- movb $0xFB, %al # mask all irq's but irq2 which -- outb %al, $0x21 # is cascaded -- --# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't --# need no steenking BIOS anyway (except for the initial loading :-). --# The BIOS-routine wants lots of unnecessary data, and it's less --# "interesting" anyway. This is how REAL programmers do it. --# --# Well, now's the time to actually move into protected mode. To make --# things as simple as possible, we do no register set-up or anything, --# we let the gnu-compiled 32-bit programs do that. We just jump to --# absolute address 0x1000 (or the loader supplied one), --# in 32-bit protected mode. --# --# Note that the short jump isn't strictly needed, although there are --# reasons why it might be a good idea. It won't hurt in any case. -- movw $1, %ax # protected mode (PE) bit -- lmsw %ax # This is it! -- jmp flush_instr -- --flush_instr: -- xorw %bx, %bx # Flag to indicate a boot -- xorl %esi, %esi # Pointer to real-mode code -- movw %cs, %si -- subw $DELTA_INITSEG, %si -- shll $4, %esi # Convert to 32-bit pointer --# NOTE: For high loaded big kernels we need a --# jmpi 0x100000,__KERNEL_CS --# --# but we yet haven't reloaded the CS register, so the default size --# of the target offset still is 16 bit. --# However, using an operand prefix (0x66), the CPU will properly --# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference --# Manual, Mixing 16-bit and 32-bit code, page 16-6) -- -- .byte 0x66, 0xea # prefix + jmpi-opcode --code32: .long 0x1000 # will be set to 0x100000 -- # for big kernels -- .word __KERNEL_CS -- --# Here's a bunch of information about your current kernel.. --kernel_version: .ascii UTS_RELEASE -- .ascii " (" -- .ascii LINUX_COMPILE_BY -- .ascii "@" -- .ascii LINUX_COMPILE_HOST -- .ascii ") " -- .ascii UTS_VERSION -- .byte 0 -- --# This is the default real mode switch routine. --# to be called just before protected mode transition --default_switch: -- cli # no interrupts allowed ! -- movb $0x80, %al # disable NMI for bootup -- # sequence -- outb %al, $0x70 -- lret -- -- --# This routine checks that the keyboard command queue is empty --# (after emptying the output buffers) --# --# Some machines have delusions that the keyboard buffer is always full --# with no keyboard attached... --# --# If there is no keyboard controller, we will usually get 0xff --# to all the reads. With each IO taking a microsecond and --# a timeout of 100,000 iterations, this can take about half a --# second ("delay" == outb to port 0x80). That should be ok, --# and should also be plenty of time for a real keyboard controller --# to empty. --# -- --empty_8042: -- pushl %ecx -- movl $100000, %ecx -- --empty_8042_loop: -- decl %ecx -- jz empty_8042_end_loop -- -- call delay -- -- inb $0x64, %al # 8042 status port -- testb $1, %al # output buffer? -- jz no_output -- -- call delay -- inb $0x60, %al # read it -- jmp empty_8042_loop -- --no_output: -- testb $2, %al # is input buffer full? -- jnz empty_8042_loop # yes - loop --empty_8042_end_loop: -- popl %ecx -- ret -- --# Read the cmos clock. Return the seconds in al --gettime: -- pushw %cx -- movb $0x02, %ah -- int $0x1a -- movb %dh, %al # %dh contains the seconds -- andb $0x0f, %al -- movb %dh, %ah -- movb $0x04, %cl -- shrb %cl, %ah -- aad -- popw %cx -- ret -- --# Delay is needed after doing I/O --delay: -- outb %al,$0x80 -- ret -- --# Descriptor tables --gdt: -- .word 0, 0, 0, 0 # dummy -- -- .word 0, 0, 0, 0 # unused -- -- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) -- .word 0 # base address = 0 -- .word 0x9A00 # code read/exec -- .word 0x00CF # granularity = 4096, 386 -- # (+5th nibble of limit) -- -- .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) -- .word 0 # base address = 0 -- .word 0x9200 # data read/write -- .word 0x00CF # granularity = 4096, 386 -- # (+5th nibble of limit) --gdt_end: --idt_48: -- .word 0 # idt limit = 0 -- .word 0, 0 # idt base = 0L --gdt_48: -- .word gdt_end-gdt-1 # gdt limit -- .word 0, 0 # gdt base (filled in later) -- --# Include video setup & detection code -- --#include "../../i386/boot/video.S" -- --# Setup signature -- must be last --setup_sig1: .word SIG1 --setup_sig2: .word SIG2 -- --# After this point, there is some free space which is used by the video mode --# handling code to store the temporary mode table (not used by the kernel). -- --modelist: -- --.text --endtext: --.data --enddata: --.bss --endbss: ---- a/arch/x86_64/boot/tools/build.c -+++ /dev/null -@@ -1,185 +0,0 @@ --/* -- * Copyright (C) 1991, 1992 Linus Torvalds -- * Copyright (C) 1997 Martin Mares -- */ -- --/* -- * This file builds a disk-image from three different files: -- * -- * - bootsect: compatibility mbr which prints an error message if -- * someone tries to boot the kernel directly. -- * - setup: 8086 machine code, sets up system parm -- * - system: 80386 code for actual system -- * -- * It does some checking that all files are of the correct type, and -- * just writes the result to stdout, removing headers and padding to -- * the right amount. It also writes some system data to stderr. -- */ -- --/* -- * Changes by tytso to allow root device specification -- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996 -- * Cross compiling fixes by Gertjan van Wingerde, July 1996 -- * Rewritten by Martin Mares, April 1997 -- */ -- --#include --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --typedef unsigned char byte; --typedef unsigned short word; --typedef unsigned long u32; -- --#define DEFAULT_MAJOR_ROOT 0 --#define DEFAULT_MINOR_ROOT 0 -- --/* Minimal number of setup sectors (see also bootsect.S) */ --#define SETUP_SECTS 4 -- --byte buf[1024]; --int fd; --int is_big_kernel; -- --void die(const char * str, ...) --{ -- va_list args; -- va_start(args, str); -- vfprintf(stderr, str, args); -- fputc('\n', stderr); -- exit(1); --} -- --void file_open(const char *name) --{ -- if ((fd = open(name, O_RDONLY, 0)) < 0) -- die("Unable to open `%s': %m", name); --} -- --void usage(void) --{ -- die("Usage: build [-b] bootsect setup system [rootdev] [> image]"); --} -- --int main(int argc, char ** argv) --{ -- unsigned int i, c, sz, setup_sectors; -- u32 sys_size; -- byte major_root, minor_root; -- struct stat sb; -- -- if (argc > 2 && !strcmp(argv[1], "-b")) -- { -- is_big_kernel = 1; -- argc--, argv++; -- } -- if ((argc < 4) || (argc > 5)) -- usage(); -- if (argc > 4) { -- if (!strcmp(argv[4], "CURRENT")) { -- if (stat("/", &sb)) { -- perror("/"); -- die("Couldn't stat /"); -- } -- major_root = major(sb.st_dev); -- minor_root = minor(sb.st_dev); -- } else if (strcmp(argv[4], "FLOPPY")) { -- if (stat(argv[4], &sb)) { -- perror(argv[4]); -- die("Couldn't stat root device."); -- } -- major_root = major(sb.st_rdev); -- minor_root = minor(sb.st_rdev); -- } else { -- major_root = 0; -- minor_root = 0; -- } -- } else { -- major_root = DEFAULT_MAJOR_ROOT; -- minor_root = DEFAULT_MINOR_ROOT; -- } -- fprintf(stderr, "Root device is (%d, %d)\n", major_root, minor_root); -- -- file_open(argv[1]); -- i = read(fd, buf, sizeof(buf)); -- fprintf(stderr,"Boot sector %d bytes.\n",i); -- if (i != 512) -- die("Boot block must be exactly 512 bytes"); -- if (buf[510] != 0x55 || buf[511] != 0xaa) -- die("Boot block hasn't got boot flag (0xAA55)"); -- buf[508] = minor_root; -- buf[509] = major_root; -- if (write(1, buf, 512) != 512) -- die("Write call failed"); -- close (fd); -- -- file_open(argv[2]); /* Copy the setup code */ -- for (i=0 ; (c=read(fd, buf, sizeof(buf)))>0 ; i+=c ) -- if (write(1, buf, c) != c) -- die("Write call failed"); -- if (c != 0) -- die("read-error on `setup'"); -- close (fd); -- -- setup_sectors = (i + 511) / 512; /* Pad unused space with zeros */ -- /* for compatibility with ancient versions of LILO. */ -- if (setup_sectors < SETUP_SECTS) -- setup_sectors = SETUP_SECTS; -- fprintf(stderr, "Setup is %d bytes.\n", i); -- memset(buf, 0, sizeof(buf)); -- while (i < setup_sectors * 512) { -- c = setup_sectors * 512 - i; -- if (c > sizeof(buf)) -- c = sizeof(buf); -- if (write(1, buf, c) != c) -- die("Write call failed"); -- i += c; -- } -- -- file_open(argv[3]); -- if (fstat (fd, &sb)) -- die("Unable to stat `%s': %m", argv[3]); -- sz = sb.st_size; -- fprintf (stderr, "System is %d kB\n", sz/1024); -- sys_size = (sz + 15) / 16; -- if (!is_big_kernel && sys_size > DEF_SYSSIZE) -- die("System is too big. Try using bzImage or modules."); -- while (sz > 0) { -- int l, n; -- -- l = (sz > sizeof(buf)) ? sizeof(buf) : sz; -- if ((n=read(fd, buf, l)) != l) { -- if (n < 0) -- die("Error reading %s: %m", argv[3]); -- else -- die("%s: Unexpected EOF", argv[3]); -- } -- if (write(1, buf, l) != l) -- die("Write failed"); -- sz -= l; -- } -- close(fd); -- -- if (lseek(1, 497, SEEK_SET) != 497) /* Write sizes to the bootsector */ -- die("Output: seek failed"); -- buf[0] = setup_sectors; -- if (write(1, buf, 1) != 1) -- die("Write of setup sector count failed"); -- if (lseek(1, 500, SEEK_SET) != 500) -- die("Output: seek failed"); -- buf[0] = (sys_size & 0xff); -- buf[1] = ((sys_size >> 8) & 0xff); -- buf[2] = ((sys_size >> 16) & 0xff); -- buf[3] = ((sys_size >> 24) & 0xff); -- if (write(1, buf, 4) != 4) -- die("Write of image length failed"); -- -- return 0; /* Everything is OK */ --} ---- a/arch/x86_64/kernel/Makefile -+++ b/arch/x86_64/kernel/Makefile -@@ -43,6 +43,7 @@ - - obj-y += topology.o - obj-y += intel_cacheinfo.o -+obj-y += addon_cpuid_features.o - obj-y += pcspeaker.o - - CFLAGS_vsyscall.o := $(PROFILING) -g0 -@@ -53,6 +54,7 @@ - topology-y += ../../i386/kernel/topology.o - microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o - intel_cacheinfo-y += ../../i386/kernel/cpu/intel_cacheinfo.o -+addon_cpuid_features-y += ../../i386/kernel/cpu/addon_cpuid_features.o - quirks-y += ../../i386/kernel/quirks.o - i8237-y += ../../i386/kernel/i8237.o - msr-$(subst m,y,$(CONFIG_X86_MSR)) += ../../i386/kernel/msr.o ---- a/arch/x86_64/kernel/setup.c -+++ b/arch/x86_64/kernel/setup.c -@@ -846,6 +846,8 @@ - c->x86_capability[2] = cpuid_edx(0x80860001); - } - -+ init_scattered_cpuid_features(c); -+ - c->apicid = phys_pkg_id(0); - - /* -@@ -931,7 +933,7 @@ - "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", - "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", - "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", -- "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, -+ "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", - - /* AMD-defined */ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -@@ -947,10 +949,11 @@ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Other (Linux-defined) */ -- "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL, -- "constant_tsc", NULL, NULL, -- "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, -- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", -+ NULL, NULL, NULL, NULL, -+ "constant_tsc", "up", NULL, "arch_perfmon", -+ "pebs", "bts", NULL, "sync_rdtsc", -+ "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - - /* Intel-defined (#2) */ -@@ -961,7 +964,7 @@ - - /* VIA/Cyrix/Centaur-defined */ - NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", -- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - -@@ -972,6 +975,12 @@ - "osvw", "ibs", NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ -+ /* Auxiliary (Linux-defined) */ -+ "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - }; - static char *x86_power_flags[] = { - "ts", /* temperature sensor */ ---- a/arch/x86_64/kernel/verify_cpu.S -+++ b/arch/x86_64/kernel/verify_cpu.S -@@ -37,20 +37,6 @@ - pushl $0 # Kill any dangerous flags - popfl - -- /* minimum CPUID flags for x86-64 as defined by AMD */ --#define M(x) (1<<(x)) --#define M2(a,b) M(a)|M(b) --#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d) -- --#define SSE_MASK \ -- (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2)) --#define REQUIRED_MASK1 \ -- (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\ -- M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\ -- M(X86_FEATURE_FXSR)) --#define REQUIRED_MASK2 \ -- (M(X86_FEATURE_LM - 32)) -- - pushfl # standard way to check for cpuid - popl %eax - movl %eax,%ebx -@@ -79,8 +65,8 @@ - verify_cpu_noamd: - movl $0x1,%eax # Does the cpu have what it takes - cpuid -- andl $REQUIRED_MASK1,%edx -- xorl $REQUIRED_MASK1,%edx -+ andl $REQUIRED_MASK0,%edx -+ xorl $REQUIRED_MASK0,%edx - jnz verify_cpu_no_longmode - - movl $0x80000000,%eax # See if extended cpuid is implemented -@@ -90,8 +76,8 @@ - - movl $0x80000001,%eax # Does the cpu have what it takes - cpuid -- andl $REQUIRED_MASK2,%edx -- xorl $REQUIRED_MASK2,%edx -+ andl $REQUIRED_MASK1,%edx -+ xorl $REQUIRED_MASK1,%edx - jnz verify_cpu_no_longmode - - verify_cpu_sse_test: ---- a/drivers/ide/legacy/hd.c -+++ b/drivers/ide/legacy/hd.c -@@ -718,74 +718,25 @@ - device_timer.function = hd_times_out; - blk_queue_hardsect_size(hd_queue, 512); - --#ifdef __i386__ - if (!NR_HD) { -- extern struct drive_info drive_info; -- unsigned char *BIOS = (unsigned char *) &drive_info; -- unsigned long flags; -- int cmos_disks; -- -- for (drive=0 ; drive<2 ; drive++) { -- hd_info[drive].cyl = *(unsigned short *) BIOS; -- hd_info[drive].head = *(2+BIOS); -- hd_info[drive].wpcom = *(unsigned short *) (5+BIOS); -- hd_info[drive].ctl = *(8+BIOS); -- hd_info[drive].lzone = *(unsigned short *) (12+BIOS); -- hd_info[drive].sect = *(14+BIOS); --#ifdef does_not_work_for_everybody_with_scsi_but_helps_ibm_vp -- if (hd_info[drive].cyl && NR_HD == drive) -- NR_HD++; --#endif -- BIOS += 16; -- } -- -- /* -- We query CMOS about hard disks : it could be that -- we have a SCSI/ESDI/etc controller that is BIOS -- compatible with ST-506, and thus showing up in our -- BIOS table, but not register compatible, and therefore -- not present in CMOS. -- -- Furthermore, we will assume that our ST-506 drives -- are the primary drives in the system, and -- the ones reflected as drive 1 or 2. -- -- The first drive is stored in the high nibble of CMOS -- byte 0x12, the second in the low nibble. This will be -- either a 4 bit drive type or 0xf indicating use byte 0x19 -- for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS. -- -- Needless to say, a non-zero value means we have -- an AT controller hard disk for that drive. -- -- Currently the rtc_lock is a bit academic since this -- driver is non-modular, but someday... ? Paul G. -- */ -- -- spin_lock_irqsave(&rtc_lock, flags); -- cmos_disks = CMOS_READ(0x12); -- spin_unlock_irqrestore(&rtc_lock, flags); -- -- if (cmos_disks & 0xf0) { -- if (cmos_disks & 0x0f) -- NR_HD = 2; -- else -- NR_HD = 1; -- } -- } --#endif /* __i386__ */ --#ifdef __arm__ -- if (!NR_HD) { -- /* We don't know anything about the drive. This means -+ /* -+ * We don't know anything about the drive. This means - * that you *MUST* specify the drive parameters to the - * kernel yourself. -+ * -+ * If we were on an i386, we used to read this info from -+ * the BIOS or CMOS. This doesn't work all that well, -+ * since this assumes that this is a primary or secondary -+ * drive, and if we're using this legacy driver, it's -+ * probably an auxilliary controller added to recover -+ * legacy data off an ST-506 drive. Either way, it's -+ * definitely safest to have the user explicitly specify -+ * the information. - */ - printk("hd: no drives specified - use hd=cyl,head,sectors" - " on kernel command line\n"); -- } --#endif -- if (!NR_HD) - goto out; -+ } - - for (drive=0 ; drive < NR_HD ; drive++) { - struct gendisk *disk = alloc_disk(64); ---- a/include/asm-i386/boot.h -+++ b/include/asm-i386/boot.h -@@ -1,5 +1,5 @@ --#ifndef _LINUX_BOOT_H --#define _LINUX_BOOT_H -+#ifndef _ASM_BOOT_H -+#define _ASM_BOOT_H - - /* Don't touch these, unless you really know what you're doing. */ - #define DEF_INITSEG 0x9000 -@@ -17,4 +17,4 @@ - + (CONFIG_PHYSICAL_ALIGN - 1)) \ - & ~(CONFIG_PHYSICAL_ALIGN - 1)) - --#endif /* _LINUX_BOOT_H */ -+#endif /* _ASM_BOOT_H */ ---- /dev/null -+++ b/include/asm-i386/bootparam.h -@@ -0,0 +1,85 @@ -+#ifndef _ASM_BOOTPARAM_H -+#define _ASM_BOOTPARAM_H -+ -+#include -+#include -+#include -+#include -+#include -+#include