[flashrom] GSoCs Winflashrom versus r126.
Luc Verhaegen
libv at skynet.be
Sun Aug 9 01:47:09 CEST 2009
Here's the diff of winflashrom versus what seems to be the closest
revision, namely r126.
diffstat:
82802ab.h | 2
Makefile | 59 +--
README | 64 +++
am29f040b.c | 4
board_enable.c | 4
chipset_enable.c | 7
direct_io.c | 654 +++++++++++++++++++++++++++++++++++++
direct_io.h | 28 +
driver/sources | 17
driver/winflashrom.c | 899 +++++++++++++++++++++++++++++++++++++++++++++++++++
driver/winflashrom.h | 83 ++++
error_msg.c | 30 +
error_msg.h | 11
flashchips.c | 3
flashrom.c | 77 +++-
interfaces.h | 81 ++++
jedec.h | 7
layout.c | 7
lbtable.c | 13
libpci/Makefile | 27 +
libpci/access.c | 282 +++++++++++++++
libpci/filter.c | 39 ++
libpci/generic.c | 214 ++++++++++++
libpci/header.h | 421 +++++++++++++++++++++++
libpci/i386-ports.c | 222 ++++++++++++
libpci/internal.h | 39 ++
libpci/pci.h | 135 +++++++
m29f400bt.h | 2
msys_doc.c | 2
sharplhf00l04.h | 3
sst49lfxxxc.c | 2
todo.txt | 11
udelay.h | 6
w39v040fa.c | 112 ++++++
w39v040fa.h | 6
winflashrom.rc | 6
36 files changed, 3528 insertions(+), 51 deletions(-)
He pulled in a copy of libpci, not sure why.
Diff created from two cleaned up copies (.svn and created files removed)
with -urN.
Have fun with it :)
Luc Verhaegen.
-------------- next part --------------
diff -urN flashrom-126/82802ab.h winflashrom/82802ab.h
--- flashrom-126/82802ab.h 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/82802ab.h 2009-08-09 01:25:02.000000000 +0200
@@ -43,7 +43,7 @@
*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
- usleep(200);
+ myusec_delay(200);
}
#endif /* !__82802AB_H__ */
diff -urN flashrom-126/am29f040b.c winflashrom/am29f040b.c
--- flashrom-126/am29f040b.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/am29f040b.c 2009-08-09 01:25:00.000000000 +0200
@@ -24,9 +24,11 @@
#include <stdio.h>
#include <stdint.h>
+#include <windows.h>
#include "flash.h"
#include "jedec.h"
#include "debug.h"
+//#include "udelay.h"
static __inline__ int erase_sector_29f040b(volatile uint8_t *bios,
unsigned long address)
@@ -38,7 +40,7 @@
*(bios + 0x2AA) = 0x55;
*(bios + address) = 0x30;
- sleep(2);
+ myusec_delay(2000000);
/* wait for Toggle bit ready */
toggle_ready_jedec(bios + address);
diff -urN flashrom-126/board_enable.c winflashrom/board_enable.c
--- flashrom-126/board_enable.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/board_enable.c 2009-08-09 01:25:00.000000000 +0200
@@ -16,13 +16,15 @@
*/
#include <stdio.h>
-#include <pci/pci.h>
+#include "libpci/pci.h"
#include <stdint.h>
#include <string.h>
#include "flash.h"
#include "debug.h"
+#include "direct_io.h"
+
/*
* Helper functions for many Winbond superIOs of the w836xx range.
*/
diff -urN flashrom-126/chipset_enable.c winflashrom/chipset_enable.c
--- flashrom-126/chipset_enable.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/chipset_enable.c 2009-08-09 01:25:00.000000000 +0200
@@ -12,12 +12,14 @@
*/
#include <stdio.h>
-#include <pci/pci.h>
+#include "libpci/pci.h"
#include <stdlib.h>
#include "flash.h"
#include "debug.h"
+#include "direct_io.h"
+
static int enable_flash_ali_m1533(struct pci_dev *dev, char *name)
{
uint8_t tmp;
@@ -333,6 +335,9 @@
if (!smbusdev) {
fprintf(stderr, "ERROR: SMBus device not found. aborting\n");
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
diff -urN flashrom-126/direct_io.c winflashrom/direct_io.c
--- flashrom-126/direct_io.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/direct_io.c 2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,654 @@
+#include <windows.h>
+#include <winioctl.h>
+#include <stdio.h>
+
+#include "interfaces.h" // Must be included after winioctl.h
+#include "direct_io.h"
+#include "error_msg.h"
+
+#define DRIVER_NAME "winflashrom"
+
+//
+// verbosity of messages
+//
+#define VEBOSE_DEBUG_MESSAGE
+#undef VEBOSE_DEBUG_MESSAGE
+
+//
+// Globals
+//
+static HANDLE h_device = INVALID_HANDLE_VALUE;
+static UCHAR driver_path[MAX_PATH];
+
+//
+// Function implementation
+//
+
+static BOOLEAN setup_driver_name( PUCHAR driver_path )
+{
+ HANDLE file_handle;
+ unsigned long err_no;
+ unsigned long driver_path_len = 0;
+
+ //
+ // Get the current directory.
+ //
+ driver_path_len = GetCurrentDirectory(MAX_PATH, driver_path );
+
+ if (!driver_path_len) {
+ err_no = GetLastError();
+ printf("GetCurrentDirectory failed! Error = %d \n",(int) err_no);
+ display_error_message(err_no);
+
+ return FALSE;
+ }
+
+ //
+ // Setup path name to driver file.
+ //
+
+ strcat(driver_path, "\\");
+ strcat(driver_path, DRIVER_NAME);
+ strcat(driver_path, ".sys");
+
+ //
+ // Insure driver file is in the specified directory.
+ //
+
+ if ((file_handle = CreateFile(driver_path,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ )) == INVALID_HANDLE_VALUE) {
+
+
+ printf("Driver: BIOS_PROBE.SYS is not in the system directory. \n");
+
+ //
+ // Indicate failure.
+ //
+
+ return FALSE;
+ }
+
+ //
+ // Close open file handle.
+ //
+
+ if (file_handle) {
+
+ CloseHandle(file_handle);
+ }
+
+ //
+ // Indicate success.
+ //
+
+ return TRUE;
+
+
+} // setup_driver_name
+
+
+static BOOL extract_driver(char *sz_driver, char *sz_out)
+/*++
+Routine Description:
+ find, load and extract the driver from resource
+
+Arguments:
+ sz_driver = resource name or number
+ sz_out = output filename
+
+Return Value:
+ FALSE = function fails
+ TRUE = function succeds
+--*/
+
+{
+ HRSRC h_res;
+ HGLOBAL h_sys;
+ LPVOID p_sys;
+ HANDLE h_file;
+ unsigned long dw_size, dw_wri;
+
+ // find and load resources, return false if failed
+ if(!(h_res = FindResource(NULL, sz_driver, TEXT("DRIVER"))))
+ return FALSE;
+
+ if(!(h_sys = LoadResource(0, h_res)))
+ return FALSE;
+
+ dw_size = SizeofResource(0, h_res);
+ p_sys = LockResource(h_sys);
+
+ // create the driver file to the choosen path
+ if((h_file = CreateFile(sz_out, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ // write the driver and and close the file handle
+ if(!WriteFile(h_file, p_sys, dw_size, &dw_wri, 0))
+ {
+ CloseHandle(h_file);
+ return FALSE;
+ }
+
+ CloseHandle(h_file);
+ return TRUE;
+}
+
+
+static BOOL activate_driver(char *sz_serv, char *sz_path, BOOL activate)
+/*++
+Routine Description:
+ register, run, stop and unregister driver
+
+Arguments:
+ sz_serv = driver service name
+ sz_path = path to driver
+ activate = register/unregisterNone
+
+Return Value:
+ 0 = function fails
+ 1 = function succeds
+--*/
+{
+ BOOL b_stat;
+ SC_HANDLE h_sc, h_sr;
+ SERVICE_STATUS srv_stat;
+
+ b_stat = FALSE;
+
+ h_sc = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
+ if(!h_sc)
+ {
+ printf("Error: failed to open service control manager\n");
+ return FALSE;
+ }
+
+ if(activate)
+ {
+ // start debug
+ printf("creating new service... \n");
+ // end debug
+
+ h_sr = CreateService(h_sc, sz_serv, sz_serv, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER,
+ SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, sz_path,
+ NULL, NULL, NULL, NULL, NULL);
+
+ if(!h_sr)
+ {
+ // start debug
+ printf("invalid service handle... \n");
+ // end debug
+
+ if(GetLastError() == ERROR_SERVICE_EXISTS)
+ {
+ h_sr = OpenService(h_sc, sz_serv, SERVICE_ALL_ACCESS);
+
+ if(!h_sr)
+ {
+ printf("Error: failed to open access to the service (service already exists)\n");
+
+ CloseServiceHandle(h_sc);
+ return FALSE;
+ }
+
+ printf("Error: service already exist!\n");
+ }
+ else
+ {
+ // start debug
+ printf("CreateService failed. But, not because of service exists :(\n");
+ // end debug
+
+ CloseServiceHandle(h_sc);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if(StartService(h_sr, 0, NULL) == 0)
+ {
+ if(ERROR_SERVICE_ALREADY_RUNNING != GetLastError())
+ {
+ CloseServiceHandle(h_sc);
+ CloseServiceHandle(h_sr);
+ return FALSE;
+ }
+ }
+ else
+ {
+ b_stat = TRUE;
+ }
+ }
+ }
+ else
+ {
+ if(!(h_sr = OpenService(h_sc, sz_serv, SERVICE_ALL_ACCESS)))
+ b_stat = FALSE;
+ else
+ b_stat = (ControlService(h_sr, SERVICE_CONTROL_STOP, &srv_stat) == 0) ? FALSE : TRUE;
+
+ // unregister the driver
+ b_stat = (DeleteService(h_sr) == 0) ? FALSE : TRUE;
+ }
+
+ // close the service handle
+ if(h_sr) CloseServiceHandle(h_sr);
+ if(h_sc) CloseServiceHandle(h_sc);
+ return b_stat;
+}
+
+
+int init_driver()
+/*++
+Routine Description:
+ Initialize the driver interface
+
+Arguments: None
+
+Return Value:
+ 0 if error
+ 1 if succeeded
+--*/
+{
+ unsigned long err_no;
+
+ //
+ // Extract the driver binary from the resource in the executable
+ //
+ if (extract_driver(TEXT("WINFLASHROMDRV"), "winflashrom.sys") == TRUE) {
+ printf("The driver has been extracted\n");
+
+ } else {
+ display_error_message(GetLastError());
+ printf("Exiting..\n");
+ return 0;
+ }
+
+
+ //
+ // Setup full path to driver name.
+ //
+ if (!setup_driver_name(driver_path)) {
+ printf("Error: failed to setup driver name \n");
+ return 0;
+ }
+
+
+ //
+ // Try to activate the driver
+ //
+ if(activate_driver(DRIVER_NAME, driver_path, TRUE) == TRUE) {
+ printf("The driver is registered and activated\n");
+ } else {
+ printf("Error: unable to register and activate the driver\n");
+ DeleteFile(driver_path);
+ return 0;
+ }
+
+ //
+ // Try to open the newly installed driver.
+ //
+
+ h_device = CreateFile( "\\\\.\\winflashrom",
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if ( h_device == INVALID_HANDLE_VALUE ){
+ err_no = GetLastError();
+ printf ( "Error: CreateFile Failed : %d\n", (int) err_no );
+ display_error_message(err_no);
+
+ // cleanup resurces created and used up to now
+ activate_driver(DRIVER_NAME, driver_path, FALSE);
+ DeleteFile(driver_path);
+
+ return 0;
+ }
+
+ return 1;
+}
+
+
+void cleanup_driver()
+{
+ //
+ // Close the access to the exported device interface in user-mode
+ //
+ if(h_device != INVALID_HANDLE_VALUE) {
+ CloseHandle(h_device);
+ }
+
+ //
+ // Unload the driver. Ignore any errors.
+ //
+ if(activate_driver(DRIVER_NAME, driver_path, FALSE) == TRUE) {
+ printf("The driver stopped and unloaded\n");
+ } else {
+ printf("Error: failed to stop and unload the driver\n");
+ }
+
+ //
+ // Delete the driver file
+ //
+ DeleteFile(driver_path);
+}
+
+
+
+unsigned char inb(unsigned short port)
+{
+ IO_BYTE ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port8 = port; // port address to read from
+
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(inl) Error: the driver handle is invalid!\n");
+ return -1;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_READ_PORT_BYTE,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ return -1;
+ }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_READ_PORT_BYTE) : %d\n",
+ bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+
+ return ioBuf.value8;
+}
+
+
+void outb(unsigned char value, unsigned short port)
+{
+ IO_BYTE ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port8 = port; // port address to write to
+ ioBuf.value8 = value;
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(outw) Error: the driver handle is invalid!\n");
+ return;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_WRITE_PORT_BYTE,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_BYTE) : %d\n",
+ bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+unsigned short inw(unsigned short port)
+{
+ IO_WORD ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port16 = port; // port address to read from
+
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(inl) Error: the driver handle is invalid!\n");
+ return -1;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_READ_PORT_WORD,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ return -1;
+ }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_READ_PORT_WORD) : %d\n",
+ bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+
+ return ioBuf.value16;
+}
+
+
+void outw(unsigned short value, unsigned short port)
+{
+ IO_WORD ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port16 = port; // port address to write to
+ ioBuf.value16 = value;
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(outw) Error: the driver handle is invalid!\n");
+ return;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_WRITE_PORT_WORD,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ }
+
+#ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_WORD) : %d\n",
+ bytes_returned);
+#endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+unsigned long inl(unsigned short port)
+{
+ IO_LONG ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port32 = port; // port address to read from
+
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(inl) Error: the driver handle is invalid!\n");
+ return -1;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_READ_PORT_LONG,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ return -1;
+ }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_READ_PORT_LONG) : %d\n",
+ bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+
+ return ioBuf.value32;
+}
+
+
+void outl(unsigned long value, unsigned short port)
+{
+ IO_LONG ioBuf;
+ unsigned long bytes_returned;
+
+ ioBuf.port32 = port; // port address to write to
+ ioBuf.value32 = value;
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(outl) Error: the driver handle is invalid!\n");
+ return;
+ }
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_WRITE_PORT_LONG,
+ &ioBuf,
+ sizeof(ioBuf),
+ &ioBuf,
+ sizeof(ioBuf),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_WRITE_PORT_LONG) : %d\n",
+ bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+}
+
+
+void* map_physical_addr_range( unsigned long phy_addr_start, unsigned long size )
+/*++
+Routine Description:
+ Maps an MMIO range.
+
+Arguments:
+ phy_addr_start - The start of physical address to be mapped.
+ size - The size of the MMIO range to map, in bytes.
+
+Return Value:
+ NULL - on error
+ pointer to the virtual address of the mapped MMIO range - on success
+
+Note:
+ - The pointer returned from this function is in the context of the
+ usermode application that use this function.
+ - You must call unmap_physical_addr_range when you are done with the
+ mapped physical memory/MMIO range that you obtain with this function.
+--*/
+{
+ MMIO_MAP mmio_map;
+ unsigned long bytes_returned;
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(map_physical_addr_range) Error: the driver handle is invalid!\n");
+ return 0; // error
+ }
+
+ mmio_map.phy_addr_start = phy_addr_start;
+ mmio_map.size = size;
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_MAP_MMIO,
+ &mmio_map,
+ sizeof(mmio_map),
+ &mmio_map,
+ sizeof(mmio_map),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ return NULL; // error
+ }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_MAP_BIOS_CHIP) : %d\n",
+ bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+
+ return mmio_map.usermode_virt_addr;
+}
+
+
+int unmap_physical_addr_range( void* virt_addr_start, unsigned long size )
+/*++
+Routine Description:
+ Unmaps a previously mapped MMIO range.
+
+Arguments:
+ virt_addr_start - The start address of the mapped physical address.
+ This parameter _must_ _be_ in the context of the
+ currently executing application. It must be a
+ pointer returned from a previous call to
+ map_physical_addr_range function.
+ size - The size of the mapped MMIO range in bytes.
+
+Return Value:
+ 0 - on error
+ 1 - on success
+
+Note:
+ This function must be called when you are done with a
+ mapped physical memory/MMIO range.
+--*/
+{
+ MMIO_MAP mmio_map;
+ unsigned long bytes_returned;
+
+ if( INVALID_HANDLE_VALUE == h_device) {
+ printf("(unmap_physical_addr_range) Error: the driver handle is invalid!\n");
+ return 0; // error
+ }
+
+ mmio_map.usermode_virt_addr = virt_addr_start;
+ mmio_map.size = size;
+
+ if( FALSE == DeviceIoControl( h_device,
+ IOCTL_UNMAP_MMIO,
+ &mmio_map,
+ sizeof(mmio_map),
+ &mmio_map,
+ sizeof(mmio_map),
+ &bytes_returned,
+ NULL))
+ {
+ display_error_message(GetLastError());
+ return 0; // error
+ }
+
+ #ifdef VEBOSE_DEBUG_MESSAGE
+ printf("number of bytes returned from kernel (IOCTL_UNMAP_BIOS_CHIP) : %d\n",
+ bytes_returned);
+ #endif //VEBOSE_DEBUG_MESSAGE
+
+ return 1; // success
+}
+
diff -urN flashrom-126/direct_io.h winflashrom/direct_io.h
--- flashrom-126/direct_io.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/direct_io.h 2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,28 @@
+#ifndef __DIRECT_IO_H__
+#define __DIRECT_IO_H__
+
+int init_driver(); // returns 0 on error, 1 on success
+void cleanup_driver(); // must be called after done using the driver
+
+void* map_physical_addr_range( unsigned long phy_addr_start,
+ unsigned long size ); // returns NULL on error, valid pointer on success
+int unmap_physical_addr_range( void* virt_addr_start,
+ unsigned long size ); // must be called after done with the mapped physical memory
+
+unsigned long hal_pci_read_offset( unsigned long bus, unsigned long device,
+ unsigned long function, unsigned long offset,
+ unsigned char length);
+
+void hal_pci_write_offset( unsigned long bus, unsigned long device,
+ unsigned long function, unsigned long offset,
+ unsigned long value, unsigned char length );
+
+void outb(unsigned char value, unsigned short port);
+void outw(unsigned short value, unsigned short port);
+void outl(unsigned long value, unsigned short port);
+
+unsigned char inb(unsigned short port);
+unsigned short inw(unsigned short port);
+unsigned long inl(unsigned short port);
+
+#endif //__DIRECT_IO_H__
diff -urN flashrom-126/driver/sources winflashrom/driver/sources
--- flashrom-126/driver/sources 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/sources 2007-06-27 02:15:18.000000000 +0200
@@ -0,0 +1,17 @@
+TARGETNAME=winflashrom
+TARGETPATH=.
+TARGETTYPE=DRIVER
+
+#
+# The WinXP DDK has introduced the DDK_TARGET_OS environemnt variable
+# for conditional compilation. The test here is designed to make this
+# sources file portable to the standalone Win 2K DDK environment. Note,
+# however, that the required csq.h and csq.lib are not present in that
+# environment.
+#
+!if "$(DDK_TARGET_OS)"!="WinXP"
+C_DEFINES=$(C_DEFINES) -DW2K=1
+TARGETLIBS=$(DDK_LIB_PATH)\csq.lib
+!endif
+
+SOURCES=winflashrom.c
diff -urN flashrom-126/driver/winflashrom.c winflashrom/driver/winflashrom.c
--- flashrom-126/driver/winflashrom.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/winflashrom.c 2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,899 @@
+/*! \file
+
+Module Name: winflashrom.c
+
+Abstract: Main file of winflashrom device driver
+
+Author: Darmawan Salihun
+
+Environment: Kernel mode
+
+Revision History:
+
+ - (June 2007) BIOS Probing device driver Modified to work with winflashrom
+ - (July 29th) MMIO mapping limited to low 1MB and 4GB-20MB to 4GB physical address range
+*/
+
+#include "winflashrom.h"
+#include <devioctl.h>
+#include "../interfaces.h"
+
+static const ULONG _1MB = 0x100000;
+static const ULONG64 _4GB = 0x100000000 ;
+static const ULONG _4GB_min_20MB = (0x100000000 - (20*0x100000));
+
+
+NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
+/*!
+
+\brief Installable driver initialization entry point.
+ This entry point is called directly by the I/O system.
+
+
+\param DriverObject - pointer to the driver object
+
+\param RegistryPath - pointer to a unicode string representing the path,
+ to driver-specific key in the registry.
+
+\retval STATUS_SUCCESS if successful,
+\retval STATUS_UNSUCCESSFUL otherwise
+
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ UNICODE_STRING unicodeDeviceName;
+ UNICODE_STRING unicodeDosDeviceName;
+ PDEVICE_OBJECT deviceObject;
+ PDEVICE_EXTENSION pDevExt;
+ ULONG i;
+
+ UNREFERENCED_PARAMETER (RegistryPath);
+
+ WINFLASHROM_KDPRINT(("DriverEntry Enter \n"));
+
+ DriverObject->DriverUnload = DispatchUnload;
+
+ DriverObject->MajorFunction[IRP_MJ_CREATE]= DispatchCreate;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
+ DriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
+
+
+ (void) RtlInitUnicodeString(&unicodeDeviceName, WINFLASHROM_DEVICE_NAME_U);
+
+ status = IoCreateDevice(
+ DriverObject,
+ sizeof(DEVICE_EXTENSION),
+ &unicodeDeviceName,
+ FILE_DEVICE_UNKNOWN,
+ 0,
+ (BOOLEAN) FALSE,
+ &deviceObject
+ );
+
+ if (!NT_SUCCESS(status))
+ {
+ return status;
+ }
+
+ WINFLASHROM_KDPRINT(("DeviceObject %p\n", deviceObject));
+
+ //
+ // Set the flag signifying that we will do direct I/O. This causes NT
+ // to lock the user buffer into memory when it's accessed
+ //
+ deviceObject->Flags |= DO_DIRECT_IO;
+
+
+ //
+ // Allocate and initialize a Unicode String containing the Win32 name
+ // for our device.
+ //
+ (void)RtlInitUnicodeString( &unicodeDosDeviceName, WINFLASHROM_DOS_DEVICE_NAME_U );
+
+
+ status = IoCreateSymbolicLink( (PUNICODE_STRING) &unicodeDosDeviceName,
+ (PUNICODE_STRING) &unicodeDeviceName );
+
+ if (!NT_SUCCESS(status))
+ {
+ IoDeleteDevice(deviceObject);
+ return status;
+ }
+
+ //
+ // Initialize device extension
+ //
+ pDevExt = (PDEVICE_EXTENSION)deviceObject->DeviceExtension;
+ for(i = 0; i < MAX_MAPPED_MMIO; i++)
+ {
+ pDevExt->mapZone[i].sysAddrBase = NULL;
+ pDevExt->mapZone[i].phyAddrStart = _4GB; // Note: _4GB is considered invalid phyAddrStart
+ pDevExt->mapZone[i].size = 0;
+ pDevExt->mapZone[i].usermodeAddrBase = NULL;
+ pDevExt->mapZone[i].pMdl = NULL;
+ }
+
+ WINFLASHROM_KDPRINT(("DriverEntry Exit = %x\n", status));
+
+ return status;
+}
+
+
+NTSTATUS DispatchCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
+/*!
+\brief
+ Process the create IRPs sent to this device.
+ This routine does nothing but signalling
+ successful IRP handling.
+
+\param DeviceObject - pointer to a device object.
+\param Irp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WINFLASHROM_KDPRINT(("DispatchCreate Enter\n"));
+
+ //
+ // The dispatch routine for IRP_MJ_CREATE is called when a
+ // file object associated with the device is created.
+ // This is typically because of a call to CreateFile() in
+ // a user-mode program or because another driver is
+ // layering itself over a this driver. A driver is
+ // required to supply a dispatch routine for IRP_MJ_CREATE.
+ //
+ WINFLASHROM_KDPRINT(("IRP_MJ_CREATE\n"));
+ Irp->IoStatus.Information = 0;
+
+ //
+ // Save Status for return and complete Irp
+ //
+ Irp->IoStatus.Status = status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ WINFLASHROM_KDPRINT((" DispatchCreate Exit = %x\n", status));
+
+ return status;
+}
+
+
+NTSTATUS ReadPortByte(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_READ_PORT_BYTE code.
+ This routine reads a byte from the designated port,
+ and returns the value to usermode application
+ through pointer to the locked-down usermode buffer
+ in the IRP.
+
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_BYTE* pUsermodeMem = (IO_BYTE*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx,[ebx].port8 ;// fetch input port addr
+ in al,dx ;// read the byte from the device
+ mov [ebx].value8, al ;// write probing result directly to user-mode memory
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+NTSTATUS ReadPortWord(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_READ_PORT_WORD code.
+ This routine reads a word from the designated port,
+ and returns the value to usermode application
+ through pointer to the locked-down usermode buffer
+ in the IRP.
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_WORD* pUsermodeMem = (IO_WORD*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx, [ebx].port16 ;// fetch input port addr
+ in ax, dx ;// read the bytes from the device
+ mov [ebx].value16, ax ;// write probing result directly to user-mode memory
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+NTSTATUS ReadPortLong(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_READ_PORT_LONG code.
+ This routine reads a DWORD from the designated port,
+ and returns the value to usermode application
+ through pointer to the locked-down usermode buffer
+ in the IRP.
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_LONG* pUsermodeMem = (IO_LONG*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx, [ebx].port32 ;// fetch input port addr
+ in eax, dx ;// read the bytes from the device
+ mov [ebx].value32, eax ;// write probing result directly to user-mode memory
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+NTSTATUS WritePortByte(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_WRITE_PORT_BYTE code.
+ This routine writes a byte to the designated port.
+ The value of the byte and the port address are obtained
+ through pointer to the locked-down buffer in the IRP.
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_BYTE* pUsermodeMem = (IO_BYTE*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx, [ebx].port8 ;// fetch input port addr
+ mov al, [ebx].value8 ;// read the value to be written directly from user-mode memory
+ out dx, al ;// write the byte to the device
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+NTSTATUS WritePortWord(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_WRITE_PORT_WORD code.
+ This routine writes a word to the designated port.
+ The value of the word and the port address are obtained
+ through pointer to the locked-down buffer in the IRP.
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_WORD* pUsermodeMem = (IO_WORD*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx, [ebx].port16 ;// fetch input port addr
+ mov ax, [ebx].value16 ;// read the value to be written directly from user-mode memory
+ out dx, ax ;// write the bytes to the device
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+NTSTATUS WritePortLong(PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_WRITE_PORT_LONG code.
+ This routine writes a dword to the designated port.
+ The value of the dword and the port address are obtained
+ through pointer to the locked-down buffer in the IRP.
+
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ IO_LONG* pUsermodeMem = (IO_LONG*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ if( NULL != pUsermodeMem) {
+ __asm
+ {
+ pushad ;// save all register contents
+
+ mov ebx, pUsermodeMem ;// build user-mode memory pointer register
+ mov dx, [ebx].port32 ;// fetch input port addr
+ mov eax, [ebx].value32 ;// read the value to be written directly from user-mode memory
+ out dx, eax ;// write the bytes to the device
+
+ popad ;// restore all saved register value
+ }
+
+ } else {
+ status = STATUS_INVALID_USER_BUFFER;
+ }
+
+ return status;
+}
+
+
+bool VerifyMmioAddressRange(ULONG64 phyAddrStart, ULONG size, PDEVICE_EXTENSION pDevExt)
+/*!
+\brief
+ Verify whether the memory-mapped I/O address range
+ requested by the user mode application lies within
+ the "correct" address range that this driver will handle.
+
+ This verification is needed to prevent user mode
+ application from mapping dangerous memory-mapped I/O
+ address range to user mode application
+
+\param phyAddrStart - starting physical address of the MMIO range to be mapped
+\param size - the size of the MMIO range to be mapped
+\param pDevExt - pointer to the DEVICE_EXTENSION of this driver
+
+\retval false if the MMIO range contains "incorrect" address range
+\retval true if the MMIO range doesn't contain "incorrect" address range
+*/
+{
+ int i;
+ ULONG64 bottom, top ;
+
+ WINFLASHROM_KDPRINT(("phyAddrStart = 0x%X \n", phyAddrStart));
+ WINFLASHROM_KDPRINT(("size = 0x%X \n", size));
+
+ /* First, check whether the MMIO range lies in the low 1MB range __or__
+ * whether the MMIO range lies between the 4GB-20MB and 4GB limit
+ */
+
+ if((phyAddrStart > _1MB ) && ((phyAddrStart + size) < _4GB_min_20MB)) {
+ return false;
+
+ } else if (phyAddrStart > _4GB) {
+ return false;
+ }
+
+ /* Now, check whether part or all of the requested physical address range
+ * has been mapped previously by the application that open access to this driver.
+ */
+
+ for(i = 0; i < MAX_MAPPED_MMIO; i++)
+ {
+ if( pDevExt->mapZone[i].phyAddrStart != _4GB)
+ {
+ bottom = pDevExt->mapZone[i].phyAddrStart;
+ top = pDevExt->mapZone[i].phyAddrStart + pDevExt->mapZone[i].size;
+
+ WINFLASHROM_KDPRINT(("pDevExt->mapZone[%u].phyAddrStart = 0x%X \n", i, pDevExt->mapZone[i].phyAddrStart));
+ WINFLASHROM_KDPRINT(("pDevExt->mapZone[%u].size = 0x%X \n", i, pDevExt->mapZone[i].size));
+
+ if( (phyAddrStart < bottom ) && ((phyAddrStart + size) > bottom) ){ // enclosing or intersection in lower limit of mapZone[i]
+ return false;
+
+ } else if ((phyAddrStart > bottom) && ((phyAddrStart + size) < top )) { // enclosed by mapZone[i]
+ return false;
+
+ } else if ((phyAddrStart < top) && ((phyAddrStart + size) > top )) { // enclosing or intersection in upper limit of mapZone[i]
+ return false;
+ }
+ }
+
+ }
+
+ return true;
+}
+
+
+
+NTSTATUS MapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_MAP_MMIO code.
+ This routine maps a physical address range
+ to the usermode application address space.
+
+ This function can only map the area
+ below the 4GB limit.
+
+\param pDO - pointer to the device object of this driver.
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ PDEVICE_EXTENSION pDevExt;
+ PHYSICAL_ADDRESS phyAddr;
+ MMIO_MAP* pUsermodeMem;
+ ULONG i, free_idx;
+
+ pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
+
+ //
+ // Check for free mapZone in the device extension.
+ // If none is free, return an error code.
+ //
+ for(i = 0; i < MAX_MAPPED_MMIO; i++)
+ {
+ if( pDevExt->mapZone[i].sysAddrBase == NULL )
+ {
+ free_idx = i;
+ break;
+ }
+ }
+
+ if( i == MAX_MAPPED_MMIO )
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // We have obtained a free mapZone, check whether the requested address range
+ // is valid and map the MMIO if it's valid
+ //
+ pUsermodeMem = (MMIO_MAP*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+ if( NULL == pUsermodeMem) {
+ return STATUS_INVALID_USER_BUFFER;
+ }
+
+ if( false == VerifyMmioAddressRange(pUsermodeMem->phy_addr_start, pUsermodeMem->size, pDevExt)){
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ phyAddr.HighPart = 0;
+ phyAddr.LowPart = pUsermodeMem->phy_addr_start;
+
+ pDevExt->mapZone[free_idx].sysAddrBase = MmMapIoSpace( phyAddr, pUsermodeMem->size, MmNonCached);
+ if(NULL == pDevExt->mapZone[free_idx].sysAddrBase) {
+ return STATUS_BUFFER_TOO_SMALL;
+
+ } else {
+ pDevExt->mapZone[free_idx].phyAddrStart = pUsermodeMem->phy_addr_start;
+ }
+
+
+ pDevExt->mapZone[free_idx].pMdl = IoAllocateMdl(pDevExt->mapZone[free_idx].sysAddrBase,
+ pUsermodeMem->size, FALSE, FALSE, NULL);
+ if(NULL == pDevExt->mapZone[free_idx].pMdl)
+ {
+ MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase, pUsermodeMem->size);
+ pDevExt->mapZone[free_idx].sysAddrBase = NULL;
+ pDevExt->mapZone[free_idx].phyAddrStart = _4GB;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ pDevExt->mapZone[free_idx].size = pUsermodeMem->size;
+
+ //
+ // Map the system virtual address to usermode virtual address
+ //
+ MmBuildMdlForNonPagedPool(pDevExt->mapZone[free_idx].pMdl);
+ pDevExt->mapZone[free_idx].usermodeAddrBase = MmMapLockedPagesSpecifyCache( pDevExt->mapZone[free_idx].pMdl,
+ UserMode, MmNonCached,
+ NULL, FALSE,
+ NormalPagePriority);
+ if(NULL == pDevExt->mapZone[free_idx].usermodeAddrBase)
+ {
+ IoFreeMdl(pDevExt->mapZone[free_idx].pMdl);
+ MmUnmapIoSpace(pDevExt->mapZone[free_idx].sysAddrBase, pDevExt->mapZone[free_idx].size);
+ pDevExt->mapZone[free_idx].sysAddrBase = NULL;
+ pDevExt->mapZone[free_idx].phyAddrStart = _4GB;
+ pDevExt->mapZone[free_idx].size = 0;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ // copy the resulting usermode virtual address to IRP "buffer"
+ pUsermodeMem->usermode_virt_addr = pDevExt->mapZone[free_idx].usermodeAddrBase;
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS CleanupMmioMapping(PDEVICE_EXTENSION pDevExt, ULONG i)
+/*!
+\brief
+ This routine cleanup the mapping of a MMIO range
+ and resources it consumes.
+
+
+\param pDevExt - pointer to the device extension of the driver
+\param i - index of the mapZone to cleanup
+
+\retval NT Status code
+*/
+{
+ if( NULL != pDevExt->mapZone[i].usermodeAddrBase )
+ {
+ MmUnmapLockedPages( pDevExt->mapZone[i].usermodeAddrBase,
+ pDevExt->mapZone[i].pMdl);
+ pDevExt->mapZone[i].usermodeAddrBase = NULL;
+ }
+
+ if( NULL != pDevExt->mapZone[i].pMdl )
+ {
+ IoFreeMdl(pDevExt->mapZone[i].pMdl);
+ pDevExt->mapZone[i].pMdl = NULL;
+ }
+
+ if( NULL != pDevExt->mapZone[i].sysAddrBase )
+ {
+ MmUnmapIoSpace( pDevExt->mapZone[i].sysAddrBase,
+ pDevExt->mapZone[i].size);
+ pDevExt->mapZone[i].sysAddrBase = NULL;
+ pDevExt->mapZone[i].phyAddrStart = _4GB;
+ pDevExt->mapZone[i].size = 0;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS UnmapMmio(PDEVICE_OBJECT pDO, PIRP pIrp)
+/*!
+\brief
+ Process the IRPs with IOCTL_UNMAP_MMIO code.
+ This routine unmaps a previously mapped physical
+ address range.
+
+ This function can only unmap the area
+ below the 4-GB limit.
+
+
+\param pDO - pointer to the device object of this driver.
+\param pIrp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ PDEVICE_EXTENSION pDevExt;
+ MMIO_MAP* pMmioMap;
+ ULONG i;
+
+ //
+ // Unmap the requested zone from the system address space
+ // and update the device extension data
+ //
+ pDevExt = (PDEVICE_EXTENSION) pDO->DeviceExtension;
+ pMmioMap = (MMIO_MAP*) MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
+
+ for(i = 0 ; i < MAX_MAPPED_MMIO; i++)
+ {
+ if(pDevExt->mapZone[i].usermodeAddrBase == pMmioMap->usermode_virt_addr)
+ {
+ CleanupMmioMapping(pDevExt, i);
+ break;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchIoControl( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+ Io control code dispatch routine
+
+\param pDO - pointer to a device object.
+\param pIrp - pointer to current Irp
+
+\retval NT status code.
+*/
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(pIrp);
+
+ switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case IOCTL_READ_PORT_BYTE:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_BYTE)) {
+ status = ReadPortByte(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_READ_PORT_WORD:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_WORD)) {
+ status = ReadPortWord(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_READ_PORT_LONG:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_LONG)) {
+ status = ReadPortLong(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_WRITE_PORT_BYTE:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_BYTE)) {
+ status = WritePortByte(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_WRITE_PORT_WORD:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_WORD)) {
+ status = WritePortWord(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_WRITE_PORT_LONG:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(IO_LONG)) {
+ status = WritePortLong(pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_MAP_MMIO:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(MMIO_MAP)) {
+ status = MapMmio(pDO, pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ case IOCTL_UNMAP_MMIO:
+ {
+ if(irpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(MMIO_MAP)) {
+ status = UnmapMmio(pDO, pIrp);
+
+ } else {
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }break;
+
+ default:
+ {
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ }break;
+ }
+
+ //
+ // complete the I/O request and return appropriate values
+ //
+ pIrp->IoStatus.Status = status;
+
+ // Set number of bytes to copy back to user-mode
+ if(status == STATUS_SUCCESS)
+ {
+ pIrp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
+ }
+ else
+ {
+ pIrp->IoStatus.Information = 0;
+ }
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+ return status;
+}
+
+
+NTSTATUS DispatchRead( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+ Read dispatch routine
+
+ This function does nothing. It's merely a place holder
+ to satisfy the need of the user mode code to open the driver
+ with a GENERIC_READ parameter.
+
+\param pDO - pointer to a device object.
+\param pIrp - pointer to current Irp
+
+\retval NT status code.
+*/
+{
+ // Just complete the I/O request right away
+ pIrp->IoStatus.Status = STATUS_SUCCESS;
+ pIrp->IoStatus.Information = 0;
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchWrite( IN PDEVICE_OBJECT pDO, IN PIRP pIrp )
+/*!
+\brief
+ Write dispatch routine
+
+ This function does nothing. It's merely a place holder
+ to satisfy the need of the user mode code to open the driver
+ with a GENERIC_WRITE parameter.
+
+\param pDO - pointer to a device object.
+\param pIrp - pointer to current Irp
+
+\retval NT status code.
+*/
+{
+ // Just complete the I/O request right away
+ pIrp->IoStatus.Status = STATUS_SUCCESS;
+ pIrp->IoStatus.Information = 0;
+ IoCompleteRequest( pIrp, IO_NO_INCREMENT );
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS DispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
+/*!
+\brief
+ Process the close IRPs sent to this device.
+
+ This function clean-up the mapped MMIO ranges that
+ haven't been cleaned-up by a "buggy" usermode application.
+
+\param DeviceObject - pointer to a device object.
+\param Irp - pointer to an I/O Request Packet.
+
+\retval NT Status code
+*/
+{
+ PDEVICE_EXTENSION pDevExt;
+ ULONG i;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ WINFLASHROM_KDPRINT(("DispatchClose Enter\n"));
+
+ pDevExt = DeviceObject->DeviceExtension ;
+
+ //
+ // Clean-up the mapped MMIO space in case the usermode
+ // application forget to call UnmapMmio for some MMIO zone.
+ // This is to guard against some buggy usermode application.
+ //
+ for(i = 0; i < MAX_MAPPED_MMIO; i++)
+ {
+ if(pDevExt->mapZone[i].sysAddrBase != NULL)
+ {
+ CleanupMmioMapping(pDevExt, i);
+ }
+ }
+
+ //
+ // The IRP_MJ_CLOSE dispatch routine is called when a file object
+ // opened on the driver is being removed from the system; that is,
+ // all file object handles have been closed and the reference count
+ // of the file object is down to 0.
+ //
+ WINFLASHROM_KDPRINT(("IRP_MJ_CLOSE\n"));
+ Irp->IoStatus.Information = 0;
+
+ //
+ // Save Status for return and complete Irp
+ //
+ Irp->IoStatus.Status = status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ WINFLASHROM_KDPRINT((" DispatchClose Exit = %x\n", status));
+
+ return status;
+}
+
+
+VOID DispatchUnload( IN PDRIVER_OBJECT DriverObject )
+/*!
+\brief
+ Free all the allocated resources, etc.
+
+\param DriverObject - pointer to a driver object.
+
+\retval VOID
+*/
+{
+ PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
+ UNICODE_STRING uniWin32NameString;
+
+ WINFLASHROM_KDPRINT(("DispatchUnload Enter\n"));
+
+ //
+ // Create counted string version of our Win32 device name.
+ //
+
+ RtlInitUnicodeString( &uniWin32NameString, WINFLASHROM_DOS_DEVICE_NAME_U );
+
+ IoDeleteSymbolicLink( &uniWin32NameString );
+
+ ASSERT(!deviceObject->AttachedDevice);
+
+ IoDeleteDevice( deviceObject );
+
+ WINFLASHROM_KDPRINT(("DispatchUnload Exit\n"));
+ return;
+}
+
+
diff -urN flashrom-126/driver/winflashrom.h winflashrom/driver/winflashrom.h
--- flashrom-126/driver/winflashrom.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/driver/winflashrom.h 2007-07-28 20:23:42.000000000 +0200
@@ -0,0 +1,83 @@
+#ifndef __WINFLASHROM_H__
+#define __WINFLASHROM_H__
+
+#include <ntddk.h>
+#include "../interfaces.h"
+
+// Debugging macros
+
+#if DBG
+#define WINFLASHROM_KDPRINT(_x_) \
+ DbgPrint("WINFLASHROM.SYS: ");\
+ DbgPrint _x_;
+#else
+
+#define WINFLASHROM_KDPRINT(_x_)
+
+#endif
+
+
+
+#define WINFLASHROM_DEVICE_NAME_U L"\\Device\\winflashrom"
+#define WINFLASHROM_DOS_DEVICE_NAME_U L"\\DosDevices\\winflashrom"
+
+
+typedef struct _MMIO_RING_0_MAP{
+ PVOID sysAddrBase; // start of system virtual address of the mapped physical address range
+ ULONG64 phyAddrStart; // start of physical address of the mapped MMIO
+ ULONG size; // size of the mapped physical address range
+ PVOID usermodeAddrBase; // pointer to the usermode virtual address where this range is mapped
+ PMDL pMdl; // Memory Descriptor List for the memory mapped I/O range to be mapped
+}MMIO_RING_0_MAP, *PMMIO_RING_0_MAP;
+
+typedef struct _DEVICE_EXTENSION{
+ MMIO_RING_0_MAP mapZone[MAX_MAPPED_MMIO];
+}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+typedef enum {false = 0, true = 1} bool;
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING registryPath
+);
+
+NTSTATUS
+DispatchCreate(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+NTSTATUS
+DispatchClose(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+DispatchUnload(
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+NTSTATUS
+DispatchRead(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+);
+
+
+NTSTATUS
+DispatchWrite(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+);
+
+NTSTATUS
+DispatchIoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+);
+
+#endif //__WINFLASHROM_H__
+
+
diff -urN flashrom-126/error_msg.c winflashrom/error_msg.c
--- flashrom-126/error_msg.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/error_msg.c 2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,30 @@
+#include <windows.h>
+#include <stdio.h>
+#include "error_msg.h"
+
+VOID display_error_message(DWORD error_number)
+{
+
+ LPVOID lpMsgBuf;
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ error_number,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ // Handle the error.
+ return;
+ }
+
+ // Display the string.
+ printf("Error! %s\n", (LPCTSTR)lpMsgBuf );
+
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+}
+
diff -urN flashrom-126/error_msg.h winflashrom/error_msg.h
--- flashrom-126/error_msg.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/error_msg.h 2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,11 @@
+#ifndef __ERROR_MSG_H__
+#define __ERROR_MSG_H__
+
+/*
+ * Note: Error number can be found easily with GetLastError() function
+ */
+
+void display_error_message(unsigned long error_number);
+
+#endif //__ERROR_MSG_H__
+
diff -urN flashrom-126/flashchips.c winflashrom/flashchips.c
--- flashrom-126/flashchips.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/flashchips.c 2009-08-09 01:25:00.000000000 +0200
@@ -32,6 +32,7 @@
#include "sst28sf040.h"
#include "sst49lfxxxc.h"
#include "w49f002u.h"
+#include "w39v040fa.h"
#include "sst39sf020.h"
#include "sst49lf040.h"
#include "pm49fl004.h"
@@ -105,7 +106,7 @@
{"W49V002FA", WINBOND_ID, W_49V002FA, 256, 128,
probe_jedec, erase_chip_jedec, write_49f002},
{"W39V040FA", WINBOND_ID, W_39V040FA, 512, 64*1024,
- probe_jedec, erase_chip_jedec, write_39sf020},
+ probe_jedec, erase_chip_jedec, write_39v040fa},
{"W39V040A", WINBOND_ID, W_39V040A, 512, 64*1024,
probe_jedec, erase_chip_jedec, write_39sf020},
{"W39V040B", WINBOND_ID, W_39V040B, 512, 64*1024,
diff -urN flashrom-126/flashrom.c winflashrom/flashrom.c
--- flashrom-126/flashrom.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/flashrom.c 2009-08-09 01:25:00.000000000 +0200
@@ -27,7 +27,6 @@
#include <errno.h>
#include <fcntl.h>
-#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -35,7 +34,14 @@
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
+
+#ifdef __MINGW32_VERSION
+#include "libpci/pci.h"
+#include "direct_io.h"
+#else
+#include <sys/mman.h>
#include <pci/pci.h>
+#endif
/* for iopl */
#if defined (__sun) && (defined(__i386) || defined(__amd64))
@@ -104,6 +110,14 @@
volatile uint8_t *registers;
size_t size = flash->total_size * 1024;
+#ifdef __MINGW32_VERSION
+ registers = map_physical_addr_range((0xFFFFFFFF - 0x400000 - size + 1), size);
+ if (registers == NULL) {
+ perror("Can't map registers");
+ cleanup_driver();
+ exit(1);
+ }
+#else
registers = mmap(0, size, PROT_WRITE | PROT_READ, MAP_SHARED,
fd_mem, (off_t) (0xFFFFFFFF - 0x400000 - size + 1));
@@ -111,6 +125,8 @@
perror("Can't mmap registers using " MEM_DEV);
exit(1);
}
+#endif
+
flash->virtual_registers = registers;
return 0;
@@ -139,6 +155,14 @@
flash_baseaddr = (0xffffffff - size + 1);
#endif
+#ifdef __MINGW32_VERSION
+ bios = map_physical_addr_range(flash_baseaddr, size);
+ if (bios == NULL) {
+ perror("Can't map bios chip");
+ cleanup_driver();
+ exit(1);
+ }
+#else
/* If getpagesize() > size ->
* "Can't mmap memory using /dev/mem: Invalid argument"
* This should never happen as we don't support any flash chips
@@ -157,6 +181,7 @@
perror("Can't mmap memory using " MEM_DEV);
exit(1);
}
+#endif //__MINGW32_VERSION
flash->virtual_memory = bios;
if (flash->probe(flash) == 1) {
@@ -164,8 +189,12 @@
flash->name, flash_baseaddr);
return flash;
}
- munmap((void *)bios, size);
+#ifdef __MINGW32_VERSION
+ unmap_physical_addr_range((void*)bios, size);
+#else
+ munmap((void *)bios, size);
+#endif
flash++;
}
return NULL;
@@ -338,29 +367,38 @@
filename = argv[optind++];
/* First get full io access */
+/* // I don't know yet how to include #ifdef __MINGW32_VERSION here :-(
#if defined (__sun) && (defined(__i386) || defined(__amd64))
if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) != 0) {
-#else
+#else
if (iopl(3) != 0) {
#endif
fprintf(stderr, "ERROR: iopl failed: \"%s\"\n",
strerror(errno));
exit(1);
}
-
+*/
+#ifdef __MINGW32_VERSION
+ if( init_driver() == 0)
+ {
+ printf("Error: failed to initialize driver interface\n");
+ exit(1);
+ }
+#endif
/* Initialize PCI access for flash enables */
pacc = pci_alloc(); /* Get the pci_access structure */
/* Set all options you want -- here we stick with the defaults */
pci_init(pacc); /* Initialize the PCI library */
pci_scan_bus(pacc); /* We want to get the list of devices */
+#ifndef __MINGW32_VERSION
/* Open the memory device. A lot of functions need it */
if ((fd_mem = open(MEM_DEV, O_RDWR)) < 0) {
perror("Error: Can not access memory using " MEM_DEV
". You need to be root.");
exit(1);
}
-
+#endif
myusec_calibrate_delay();
/* We look at the lbtable first to see if we need a
@@ -381,6 +419,9 @@
if ((flash = probe_flash(flashchips)) == NULL) {
printf("No EEPROM/flash device found.\n");
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
@@ -389,6 +430,9 @@
if (!filename && !erase_it) {
// FIXME: Do we really want this feature implicitly?
printf("OK, only ENABLING flash write, but NOT FLASHING.\n");
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
return 0;
}
@@ -398,10 +442,16 @@
if (erase_it) {
printf("Erasing flash chip\n");
flash->erase(flash);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(0);
} else if (read_it) {
- if ((image = fopen(filename, "w")) == NULL) {
+ if ((image = fopen(filename, "wb")) == NULL) {
perror(filename);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
printf("Reading Flash...");
@@ -420,16 +470,25 @@
} else {
struct stat image_stat;
- if ((image = fopen(filename, "r")) == NULL) {
+ if ((image = fopen(filename, "rb")) == NULL) {
perror(filename);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
if (fstat(fileno(image), &image_stat) != 0) {
perror(filename);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
if (image_stat.st_size != flash->total_size * 1024) {
fprintf(stderr, "Error: Image size doesnt match\n");
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
@@ -471,5 +530,9 @@
if (verify_it)
ret |= verify_flash(flash, buf);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
return ret;
}
+
diff -urN flashrom-126/interfaces.h winflashrom/interfaces.h
--- flashrom-126/interfaces.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/interfaces.h 2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,81 @@
+/*
+ * This is the interface file that connects the user mode application and the kernel mode driver
+ *
+ * NOTE:
+ * -----
+ * - You __have__ to put #include <winioctl.h> prior to including this file in your user mode application
+ * - You probably need to put #include <devioctl.h> prior to including this file in your kernel mode driver
+ * These includes are needed for the CTL_CODE macro to work.
+ */
+
+#ifndef __INTERFACES_H__
+#define __INTERFACES_H__
+
+#define IOCTL_READ_PORT_BYTE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0801, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_READ_PORT_WORD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0802, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_READ_PORT_LONG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0803, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+#define IOCTL_WRITE_PORT_BYTE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0804, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_WRITE_PORT_WORD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0805, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_WRITE_PORT_LONG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0806, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+#define IOCTL_MAP_MMIO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x0809, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+#define IOCTL_UNMAP_MMIO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x080A, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
+
+
+#ifdef __GNUC__ // are we using GCC to compile this code?
+#define PACK_STRUC __attribute__((packed))
+#else
+#define PACK_STRUC
+#endif
+
+
+enum {
+ MAX_MAPPED_MMIO = 256 // maximum number of mapped memory-mapped I/O zones
+};
+
+#ifdef _MSC_VER // are we using MSVC to compile this code?
+#pragma pack (push, 1)
+#endif
+
+struct _IO_BYTE {
+ unsigned short port8;
+ unsigned char value8;
+}PACK_STRUC;
+typedef struct _IO_BYTE IO_BYTE;
+
+struct _IO_WORD {
+ unsigned short port16;
+ unsigned short value16;
+}PACK_STRUC;
+typedef struct _IO_WORD IO_WORD;
+
+struct _IO_LONG {
+ unsigned short port32;
+ unsigned long value32;
+}PACK_STRUC;
+typedef struct _IO_LONG IO_LONG;
+
+struct _MMIO_MAP {
+ unsigned long phy_addr_start; // start address in physical address space to be mapped
+ unsigned long size; // size of the physical address space to map
+ void * usermode_virt_addr; // starting virtual address of the MMIO as seen from user mode
+}PACK_STRUC;
+typedef struct _MMIO_MAP MMIO_MAP;
+
+struct _PCI_ADDRESS {
+ unsigned long bus;
+ unsigned long device;
+ unsigned long function;
+ unsigned long value;
+ unsigned char offset;
+ unsigned char length; // length of the value to be written/read in bytes
+}PACK_STRUC;
+typedef struct _PCI_ADDRESS PCI_ADDRESS;
+
+#ifdef _MSC_VER // are we using MSVC to compile this code?
+#pragma pack (pop)
+#endif
+
+
+#endif //__INTERFACES_H__
diff -urN flashrom-126/jedec.h winflashrom/jedec.h
--- flashrom-126/jedec.h 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/jedec.h 2009-08-09 01:25:02.000000000 +0200
@@ -1,5 +1,8 @@
#ifndef __JEDEC_H__
#define __JEDEC_H__ 1
+
+#include "udelay.h"
+
int write_byte_program_jedec(volatile uint8_t *bios, uint8_t *src,
volatile uint8_t *dst);
@@ -51,7 +54,7 @@
*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
*(volatile uint8_t *)(bios + 0x5555) = 0x20;
- usleep(200);
+ myusec_delay(200);
}
extern __inline__ void protect_jedec(volatile uint8_t *bios)
@@ -60,7 +63,7 @@
*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
- usleep(200);
+ myusec_delay(200);
}
#endif /* !__JEDEC_H__ */
diff -urN flashrom-126/layout.c winflashrom/layout.c
--- flashrom-126/layout.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/layout.c 2009-08-09 01:25:00.000000000 +0200
@@ -6,6 +6,10 @@
#include "lbtable.h"
#include "debug.h"
+#ifdef __MINGW32_VERSION
+#include "direct_io.h"
+#endif
+
char *mainboard_vendor = NULL;
char *mainboard_part = NULL;
int romimages = 0;
@@ -90,6 +94,9 @@
"values with --mainboard <vendor>:<mainboard>.\n\n",
mainboard_vendor, mainboard_part, lb_vendor,
lb_part);
+#ifdef __MINGW32_VERSION
+ cleanup_driver();
+#endif
exit(1);
}
}
diff -urN flashrom-126/lbtable.c winflashrom/lbtable.c
--- flashrom-126/lbtable.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/lbtable.c 2009-08-09 01:25:00.000000000 +0200
@@ -29,10 +29,10 @@
#include <sys/types.h>
#include <string.h>
#include <errno.h>
-#include <sys/mman.h>
#include "flash.h"
#include "linuxbios_tables.h"
#include "debug.h"
+#include "direct_io.h"
char *lb_part = NULL, *lb_vendor = NULL;
@@ -181,12 +181,23 @@
struct lb_header *lb_table;
struct lb_record *rec, *last;
+#ifdef __MINGW32_VERSION
+ low_1MB = map_physical_addr_range(0x00000000, 1024 * 1024);
+ if (low_1MB == NULL) {
+ perror("Can't map low 1MB");
+ cleanup_driver();
+ exit(-2);
+ }
+#else
low_1MB = mmap(0, 1024 * 1024, PROT_READ, MAP_SHARED, fd_mem,
0x00000000);
if (low_1MB == MAP_FAILED) {
perror("Can't mmap memory using " MEM_DEV);
exit(-2);
}
+#endif
+
+
lb_table = 0;
if (!lb_table)
lb_table = find_lb_table(low_1MB, 0x00000, 0x1000);
diff -urN flashrom-126/libpci/access.c winflashrom/libpci/access.c
--- flashrom-126/libpci/access.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/access.c 2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,282 @@
+/*
+ * $Id: access.c,v 1.10 2003/01/04 11:04:39 mj Exp $
+ *
+ * The PCI Library -- User Access
+ *
+ * Copyright (c) 1997--1999 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "internal.h"
+
+static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
+ &pm_intel_conf1,
+ &pm_intel_conf2,
+};
+
+struct pci_access *
+pci_alloc(void)
+{
+ struct pci_access *a = malloc(sizeof(struct pci_access));
+ int i;
+
+ memset(a, 0, sizeof(*a));
+ for(i=0; i<PCI_ACCESS_MAX; i++)
+ if (pci_methods[i] && pci_methods[i]->config)
+ pci_methods[i]->config(a);
+ return a;
+}
+
+void *
+pci_malloc(struct pci_access *a, int size)
+{
+ void *x = malloc(size);
+
+ if (!x)
+ a->error("Out of memory (allocation of %d bytes failed)", size);
+ return x;
+}
+
+void
+pci_mfree(void *x)
+{
+ if (x)
+ free(x);
+}
+
+static void
+pci_generic_error(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fputs("pcilib: ", stderr);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+static void
+pci_generic_warn(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ fputs("pcilib: ", stderr);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+}
+
+static void
+pci_generic_debug(char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+ vfprintf(stdout, msg, args);
+ va_end(args);
+}
+
+
+void
+pci_init(struct pci_access *a)
+{
+ if (!a->error)
+ a->error = pci_generic_error;
+ if (!a->warning)
+ a->warning = pci_generic_warn;
+ if (!a->debug)
+ a->debug = pci_generic_debug;
+
+ if (a->method)
+ {
+ if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
+ a->error("This access method is not supported.\n");
+ a->methods = pci_methods[a->method];
+ }
+ else
+ {
+ unsigned int i;
+ for(i=0; i<PCI_ACCESS_MAX; i++)
+ if (pci_methods[i])
+ {
+ a->debug("Trying method %d...\n", i);
+ if (pci_methods[i]->detect(a))
+ {
+ a->debug("...OK\n");
+ a->methods = pci_methods[i];
+ a->method = i;
+ break;
+ }
+ a->debug("...No.\n");
+ }
+ if (!a->methods)
+ a->error("Cannot find any working access method.");
+ }
+ a->debug("Decided to use %s\n", a->methods->name);
+
+ if( NULL != a->methods->init )
+ {
+ a->methods->init(a); //this is the bug, we don't need iopl3 init in windows
+ }
+}
+
+void
+pci_cleanup(struct pci_access *a)
+{
+ struct pci_dev *d, *e;
+
+ for(d=a->devices; d; d=e)
+ {
+ e = d->next;
+ pci_free_dev(d);
+ }
+
+ if (a->methods)
+ {
+ if( a->methods->cleanup != NULL )
+ { a->methods->cleanup(a); } //this is the bug, we don't need iopl3 cleanup in windows
+ }
+
+ pci_mfree(a);
+}
+
+void
+pci_scan_bus(struct pci_access *a)
+{
+ a->methods->scan(a);
+}
+
+struct pci_dev *
+pci_alloc_dev(struct pci_access *a)
+{
+ struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev));
+
+ memset(d, 0, sizeof(*d));
+ d->access = a;
+ d->methods = a->methods;
+ if (d->methods->init_dev)
+ d->methods->init_dev(d);
+ return d;
+}
+
+int
+pci_link_dev(struct pci_access *a, struct pci_dev *d)
+{
+ d->next = a->devices;
+ a->devices = d;
+
+ return 1;
+}
+
+struct pci_dev *
+pci_get_dev(struct pci_access *a, word bus, byte dev, byte func)
+{
+ struct pci_dev *d = pci_alloc_dev(a);
+
+ d->bus = bus;
+ d->dev = dev;
+ d->func = func;
+ return d;
+}
+
+void pci_free_dev(struct pci_dev *d)
+{
+ if (d->methods->cleanup_dev)
+ d->methods->cleanup_dev(d);
+ pci_mfree(d);
+}
+
+static void
+pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
+{
+ if (pos & (len-1))
+ d->access->error("Unaligned read: pos=%02x, len=%d", pos, len);
+ else if (!d->methods->read(d, pos, buf, len))
+ memset(buf, 0xff, len);
+}
+
+byte
+pci_read_byte(struct pci_dev *d, int pos)
+{
+ byte buf;
+ pci_read_data(d, &buf, pos, 1);
+ return buf;
+}
+
+word
+pci_read_word(struct pci_dev *d, int pos)
+{
+ word buf;
+ pci_read_data(d, &buf, pos, 2);
+ return buf;
+}
+
+u32
+pci_read_long(struct pci_dev *d, int pos)
+{
+ u32 buf;
+ pci_read_data(d, &buf, pos, 4);
+ return buf;
+}
+
+int
+pci_read_block(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ return d->methods->read(d, pos, buf, len);
+}
+
+static int
+pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
+{
+ if (pos & (len-1))
+ d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
+ return d->methods->write(d, pos, buf, len);
+}
+
+int
+pci_write_byte(struct pci_dev *d, int pos, byte data)
+{
+ return pci_write_data(d, &data, pos, 1);
+}
+
+int
+pci_write_word(struct pci_dev *d, int pos, word data)
+{
+ word buf = data;
+ return pci_write_data(d, &buf, pos, 2);
+}
+
+int
+pci_write_long(struct pci_dev *d, int pos, u32 data)
+{
+ u32 buf = data;
+ return pci_write_data(d, &buf, pos, 4);
+}
+
+int
+pci_write_block(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ return d->methods->write(d, pos, buf, len);
+}
+
+int
+pci_fill_info(struct pci_dev *d, int flags)
+{
+ if (flags & PCI_FILL_RESCAN)
+ {
+ flags &= ~PCI_FILL_RESCAN;
+ d->known_fields = 0;
+ }
+ if (flags & ~d->known_fields)
+ d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
+ return d->known_fields;
+}
+
+
diff -urN flashrom-126/libpci/filter.c winflashrom/libpci/filter.c
--- flashrom-126/libpci/filter.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/filter.c 2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * $Id: filter.c,v 1.3 2002/03/30 15:39:25 mj Exp $
+ *
+ * Linux PCI Library -- Device Filtering
+ *
+ * Copyright (c) 1998--2002 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "internal.h"
+
+void
+pci_filter_init(struct pci_access * a, struct pci_filter *f)
+{
+ f->bus = f->slot = f->func = -1;
+ f->vendor = f->device = -1;
+}
+
+
+int
+pci_filter_match(struct pci_filter *f, struct pci_dev *d)
+{
+ if ((f->bus >= 0 && f->bus != d->bus) ||
+ (f->slot >= 0 && f->slot != d->dev) ||
+ (f->func >= 0 && f->func != d->func))
+ return 0;
+ if (f->device >= 0 || f->vendor >= 0)
+ {
+ pci_fill_info(d, PCI_FILL_IDENT);
+ if ((f->device >= 0 && f->device != d->device_id) ||
+ (f->vendor >= 0 && f->vendor != d->vendor_id))
+ return 0;
+ }
+ return 1;
+}
diff -urN flashrom-126/libpci/generic.c winflashrom/libpci/generic.c
--- flashrom-126/libpci/generic.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/generic.c 2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,214 @@
+/*
+ * $Id: generic.c,v 1.8 2002/12/27 19:01:51 mj Exp $
+ *
+ * The PCI Library -- Generic Direct Access Functions
+ *
+ * Copyright (c) 1997--2000 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <string.h>
+
+#include "internal.h"
+
+void
+pci_generic_scan_bus(struct pci_access *a, byte *busmap, word bus)
+{
+ int multi, ht;
+ u32 vd;
+ u8 dev;
+ struct pci_dev *d;
+
+ struct pci_dev *t = pci_alloc_dev(a);
+
+ a->debug("Scanning bus %02x for devices...\n", bus);
+ if (busmap[bus])
+ {
+ a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
+ return;
+ }
+ busmap[bus] = 1;
+ t->bus = bus;
+ for(dev=0; dev<32; dev++)
+ {
+ t->dev = dev;
+ multi = 0;
+ for(t->func=0; !t->func || (multi && t->func<8); t->func++)
+ {
+ vd = pci_read_long(t, PCI_VENDOR_ID);
+
+ if (!vd || vd == 0xffffffff)
+ continue;
+ ht = pci_read_byte(t, PCI_HEADER_TYPE);
+ if (!t->func)
+ multi = ht & 0x80;
+ ht &= 0x7f;
+ d = pci_alloc_dev(a);
+ d->bus = t->bus;
+ d->dev = t->dev;
+ d->func = t->func;
+ d->vendor_id = (word)(vd & 0xffff);
+ d->device_id = (word)(vd >> 16U);
+ d->known_fields = PCI_FILL_IDENT;
+ d->hdrtype = ht;
+ pci_link_dev(a, d);
+ switch (ht)
+ {
+ case PCI_HEADER_TYPE_NORMAL:
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ case PCI_HEADER_TYPE_CARDBUS:
+ pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
+ break;
+ default:
+ a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
+ }
+ }
+ }
+}
+
+void
+pci_generic_scan(struct pci_access *a)
+{
+ byte busmap[256];
+
+ memset(busmap, 0, sizeof(busmap));
+ pci_generic_scan_bus(a, busmap, 0);
+}
+
+int
+pci_generic_fill_info(struct pci_dev *d, int flags)
+{
+ struct pci_access *a = d->access;
+
+ if (flags & PCI_FILL_IDENT)
+ {
+ d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
+ d->device_id = pci_read_word(d, PCI_DEVICE_ID);
+ }
+ if (flags & PCI_FILL_IRQ)
+ d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
+ if (flags & PCI_FILL_BASES)
+ {
+ int cnt = 0, i;
+ memset(d->base_addr, 0, sizeof(d->base_addr));
+ switch (d->hdrtype)
+ {
+ case PCI_HEADER_TYPE_NORMAL:
+ cnt = 6;
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ cnt = 2;
+ break;
+ case PCI_HEADER_TYPE_CARDBUS:
+ cnt = 1;
+ break;
+ }
+ if (cnt)
+ {
+ u16 cmd = pci_read_word(d, PCI_COMMAND);
+ for(i=0; i<cnt; i++)
+ {
+ u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
+ if (!x || x == (u32) ~0)
+ continue;
+ d->base_addr[i] = x;
+ if (x & PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ if (!a->buscentric && !(cmd & PCI_COMMAND_IO))
+ d->base_addr[i] = 0;
+ }
+ else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY))
+ {
+ if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+ if (i >= cnt-1)
+ a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
+ else
+ {
+ u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
+#ifdef HAVE_64BIT_ADDRESS
+ d->base_addr[i-1] |= ((pciaddr_t) y) << 32;
+#else
+ if (y)
+ {
+ a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
+ d->base_addr[i-1] = 0;
+ }
+#endif
+ }
+ }
+ }
+ else
+ d->base_addr[i] = 0;
+ }
+ }
+ }
+ if (flags & PCI_FILL_ROM_BASE)
+ {
+ int reg = 0;
+ d->rom_base_addr = 0;
+ switch (d->hdrtype)
+ {
+ case PCI_HEADER_TYPE_NORMAL:
+ reg = PCI_ROM_ADDRESS;
+ break;
+ case PCI_HEADER_TYPE_BRIDGE:
+ reg = PCI_ROM_ADDRESS1;
+ break;
+ }
+ if (reg)
+ {
+ u32 a = pci_read_long(d, reg);
+ if (a & PCI_ROM_ADDRESS_ENABLE)
+ d->rom_base_addr = a;
+ }
+ }
+ return flags & ~PCI_FILL_SIZES;
+}
+
+static int
+pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
+ int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
+{
+ if ((pos & 1) && len >= 1)
+ {
+ if (!r(d, pos, buf, 1))
+ return 0;
+ pos++; buf++; len--;
+ }
+ if ((pos & 3) && len >= 2)
+ {
+ if (!r(d, pos, buf, 2))
+ return 0;
+ pos += 2; buf += 2; len -= 2;
+ }
+ while (len >= 4)
+ {
+ if (!r(d, pos, buf, 4))
+ return 0;
+ pos += 4; buf += 4; len -= 4;
+ }
+ if (len >= 2)
+ {
+ if (!r(d, pos, buf, 2))
+ return 0;
+ pos += 2; buf += 2; len -= 2;
+ }
+ if (len && !r(d, pos, buf, 1))
+ return 0;
+ return 1;
+}
+
+int
+pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
+}
+
+int
+pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
+}
diff -urN flashrom-126/libpci/header.h winflashrom/libpci/header.h
--- flashrom-126/libpci/header.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/header.h 2007-06-27 02:13:02.000000000 +0200
@@ -0,0 +1,421 @@
+/*
+ * $Id: header.h,v 1.9 2002/12/26 20:24:50 mj Exp $
+ *
+ * The PCI Library -- PCI Header Structure (extracted from <linux/pci.h>)
+ *
+ * Copyright (c) 1997--2002 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+
+#define PCI_STATUS 0x06 /* 16 bits */
+#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
+#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
+#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
+#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
+#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
+#define PCI_STATUS_DEVSEL_FAST 0x000
+#define PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define PCI_STATUS_DEVSEL_SLOW 0x400
+#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8
+ revision */
+#define PCI_REVISION_ID 0x08 /* Revision ID */
+#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
+#define PCI_HEADER_TYPE 0x0e /* 8 bits */
+#define PCI_HEADER_TYPE_NORMAL 0
+#define PCI_HEADER_TYPE_BRIDGE 1
+#define PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of
+ * 0xffffffff to the register, and reading it back. Only
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS 0x28
+#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define PCI_SUBSYSTEM_ID 0x2e
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK ~0x0f
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK ~0x0f
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+/* 0x14-0x15 reserved */
+#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
+#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
+#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0 0x1c
+#define PCI_CB_MEMORY_LIMIT_0 0x20
+#define PCI_CB_MEMORY_BASE_1 0x24
+#define PCI_CB_MEMORY_LIMIT_1 0x28
+#define PCI_CB_IO_BASE_0 0x2c
+#define PCI_CB_IO_BASE_0_HI 0x2e
+#define PCI_CB_IO_LIMIT_0 0x30
+#define PCI_CB_IO_LIMIT_0_HI 0x32
+#define PCI_CB_IO_BASE_1 0x34
+#define PCI_CB_IO_BASE_1_HI 0x36
+#define PCI_CB_IO_LIMIT_1 0x38
+#define PCI_CB_IO_LIMIT_1_HI 0x3a
+#define PCI_CB_IO_RANGE_MASK ~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL 0x3e
+#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
+#define PCI_CB_BRIDGE_CTL_SERR 0x02
+#define PCI_CB_BRIDGE_CTL_ISA 0x04
+#define PCI_CB_BRIDGE_CTL_VGA 0x08
+#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
+#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID 0x42
+#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID 0 /* Capability ID */
+#define PCI_CAP_ID_PM 0x01 /* Power Management */
+#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
+#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
+#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
+#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF 4
+
+/* Power Management Registers */
+
+#define PCI_PM_CAP_VER_MASK 0x0007 /* Version (2=PM1.1) */
+#define PCI_PM_CAP_PME_CLOCK 0x0008 /* Clock required for PME generation */
+#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization required */
+#define PCI_PM_CAP_AUX_C_MASK 0x01c0 /* Maximum aux current required in D3cold */
+#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
+#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
+#define PCI_PM_CAP_PME_D0 0x0800 /* PME can be asserted from D0 */
+#define PCI_PM_CAP_PME_D1 0x1000 /* PME can be asserted from D1 */
+#define PCI_PM_CAP_PME_D2 0x2000 /* PME can be asserted from D2 */
+#define PCI_PM_CAP_PME_D3_HOT 0x4000 /* PME can be asserted from D3hot */
+#define PCI_PM_CAP_PME_D3_COLD 0x8000 /* PME can be asserted from D3cold */
+#define PCI_PM_CTRL 4 /* PM control and status register */
+#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
+#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
+#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* PM table data index */
+#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* PM table data scaling factor */
+#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions */
+#define PCI_PM_PPB_B2_B3 0x40 /* If bridge enters D3hot, bus enters: 0=B3, 1=B2 */
+#define PCI_PM_BPCC_ENABLE 0x80 /* Secondary bus is power managed */
+#define PCI_PM_DATA_REGISTER 7 /* PM table contents read here */
+#define PCI_PM_SIZEOF 8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION 2 /* BCD version number */
+#define PCI_AGP_RFU 3 /* Rest of capability flags */
+#define PCI_AGP_STATUS 4 /* Status register */
+#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
+#define PCI_AGP_STATUS_ISOCH 0x10000 /* Isochronous transactions supported */
+#define PCI_AGP_STATUS_ARQSZ_MASK 0xe000 /* log2(optimum async req size in bytes) - 4 */
+#define PCI_AGP_STATUS_CAL_MASK 0x1c00 /* Calibration cycle timing */
+#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
+#define PCI_AGP_STATUS_ITA_COH 0x0100 /* In-aperture accesses always coherent */
+#define PCI_AGP_STATUS_GART64 0x0080 /* 64-bit GART entries supported */
+#define PCI_AGP_STATUS_HTRANS 0x0040 /* If 0, core logic can xlate host CPU accesses thru aperture */
+#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing cycles supported */
+#define PCI_AGP_STATUS_FW 0x0010 /* Fast write transfers supported */
+#define PCI_AGP_STATUS_AGP3 0x0008 /* AGP3 mode supported */
+#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported (RFU in AGP3 mode) */
+#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported (8x in AGP3 mode) */
+#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported (4x in AGP3 mode) */
+#define PCI_AGP_COMMAND 8 /* Control register */
+#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
+#define PCI_AGP_COMMAND_ARQSZ_MASK 0xe000 /* log2(optimum async req size in bytes) - 4 */
+#define PCI_AGP_COMMAND_CAL_MASK 0x1c00 /* Calibration cycle timing */
+#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
+#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
+#define PCI_AGP_COMMAND_GART64 0x0080 /* 64-bit GART entries enabled */
+#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow generation of 64-bit addr cycles */
+#define PCI_AGP_COMMAND_FW 0x0010 /* Enable FW transfers */
+#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate (RFU in AGP3 mode) */
+#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate (8x in AGP3 mode) */
+#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate (4x in AGP3 mode) */
+#define PCI_AGP_SIZEOF 12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+
+/* PCI-X */
+#define PCI_PCIX_COMMAND 2 /* Command register offset */
+#define PCI_PCIX_COMMAND_DPERE 0x0001 /* Data Parity Error Recover Enable */
+#define PCI_PCIX_COMMAND_ERO 0x0002 /* Enable Relaxed Ordering */
+#define PCI_PCIX_COMMAND_MAX_MEM_READ_BYTE_COUNT 0x000c /* Maximum Memory Read Byte Count */
+#define PCI_PCIX_COMMAND_MAX_OUTSTANDING_SPLIT_TRANS 0x0070
+#define PCI_PCIX_COMMAND_RESERVED 0xf80
+#define PCI_PCIX_STATUS 4 /* Status register offset */
+#define PCI_PCIX_STATUS_FUNCTION 0x00000007
+#define PCI_PCIX_STATUS_DEVICE 0x000000f8
+#define PCI_PCIX_STATUS_BUS 0x0000ff00
+#define PCI_PCIX_STATUS_64BIT 0x00010000
+#define PCI_PCIX_STATUS_133MHZ 0x00020000
+#define PCI_PCIX_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */
+#define PCI_PCIX_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */
+#define PCI_PCIX_STATUS_DEVICE_COMPLEXITY 0x00100000 /* 0 = simple device, 1 = bridge device */
+#define PCI_PCIX_STATUS_DESIGNED_MAX_MEM_READ_BYTE_COUNT 0x00600000 /* 0 = 512 bytes, 1 = 1024, 2 = 2048, 3 = 4096 */
+#define PCI_PCIX_STATUS_DESIGNED_MAX_OUTSTANDING_SPLIT_TRANS 0x03800000
+#define PCI_PCIX_STATUS_DESIGNED_MAX_CUMULATIVE_READ_SIZE 0x1c000000
+#define PCI_PCIX_STATUS_RCVD_SC_ERR_MESS 0x20000000 /* Received Split Completion Error Message */
+#define PCI_PCIX_STATUS_RESERVED 0xc0000000
+#define PCI_PCIX_SIZEOF 4
+
+/* PCI-X Bridges */
+#define PCI_PCIX_BRIDGE_SEC_STATUS 2 /* Secondary bus status register offset */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_64BIT 0x0001
+#define PCI_PCIX_BRIDGE_SEC_STATUS_133MHZ 0x0002
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_DISCARDED 0x0004 /* Split Completion Discarded on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_UNEXPECTED_SC 0x0008 /* Unexpected Split Completion on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SC_OVERRUN 0x0010 /* Split Completion Overrun on secondary bus */
+#define PCI_PCIX_BRIDGE_SEC_STATUS_SPLIT_REQUEST_DELAYED 0x0020
+#define PCI_PCIX_BRIDGE_SEC_STATUS_CLOCK_FREQ 0x01c0
+#define PCI_PCIX_BRIDGE_SEC_STATUS_RESERVED 0xfe00
+#define PCI_PCIX_BRIDGE_STATUS 4 /* Primary bus status register offset */
+#define PCI_PCIX_BRIDGE_STATUS_FUNCTION 0x00000007
+#define PCI_PCIX_BRIDGE_STATUS_DEVICE 0x000000f8
+#define PCI_PCIX_BRIDGE_STATUS_BUS 0x0000ff00
+#define PCI_PCIX_BRIDGE_STATUS_64BIT 0x00010000
+#define PCI_PCIX_BRIDGE_STATUS_133MHZ 0x00020000
+#define PCI_PCIX_BRIDGE_STATUS_SC_DISCARDED 0x00040000 /* Split Completion Discarded */
+#define PCI_PCIX_BRIDGE_STATUS_UNEXPECTED_SC 0x00080000 /* Unexpected Split Completion */
+#define PCI_PCIX_BRIDGE_STATUS_SC_OVERRUN 0x00100000 /* Split Completion Overrun */
+#define PCI_PCIX_BRIDGE_STATUS_SPLIT_REQUEST_DELAYED 0x00200000
+#define PCI_PCIX_BRIDGE_STATUS_RESERVED 0xffc00000
+#define PCI_PCIX_BRIDGE_UPSTREAM_SPLIT_TRANS_CTRL 8 /* Upstream Split Transaction Register offset */
+#define PCI_PCIX_BRIDGE_DOWNSTREAM_SPLIT_TRANS_CTRL 12 /* Downstream Split Transaction Register offset */
+#define PCI_PCIX_BRIDGE_STR_CAPACITY 0x0000ffff
+#define PCI_PCIX_BRIDGE_STR_COMMITMENT_LIMIT 0xffff0000
+#define PCI_PCIX_BRIDGE_SIZEOF 12
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 7:3 = slot
+ * 2:0 = function
+ */
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+
+/* Device classes and subclasses */
+
+#define PCI_CLASS_NOT_DEFINED 0x0000
+#define PCI_CLASS_NOT_DEFINED_VGA 0x0001
+
+#define PCI_BASE_CLASS_STORAGE 0x01
+#define PCI_CLASS_STORAGE_SCSI 0x0100
+#define PCI_CLASS_STORAGE_IDE 0x0101
+#define PCI_CLASS_STORAGE_FLOPPY 0x0102
+#define PCI_CLASS_STORAGE_IPI 0x0103
+#define PCI_CLASS_STORAGE_RAID 0x0104
+#define PCI_CLASS_STORAGE_OTHER 0x0180
+
+#define PCI_BASE_CLASS_NETWORK 0x02
+#define PCI_CLASS_NETWORK_ETHERNET 0x0200
+#define PCI_CLASS_NETWORK_TOKEN_RING 0x0201
+#define PCI_CLASS_NETWORK_FDDI 0x0202
+#define PCI_CLASS_NETWORK_ATM 0x0203
+#define PCI_CLASS_NETWORK_OTHER 0x0280
+
+#define PCI_BASE_CLASS_DISPLAY 0x03
+#define PCI_CLASS_DISPLAY_VGA 0x0300
+#define PCI_CLASS_DISPLAY_XGA 0x0301
+#define PCI_CLASS_DISPLAY_OTHER 0x0380
+
+#define PCI_BASE_CLASS_MULTIMEDIA 0x04
+#define PCI_CLASS_MULTIMEDIA_VIDEO 0x0400
+#define PCI_CLASS_MULTIMEDIA_AUDIO 0x0401
+#define PCI_CLASS_MULTIMEDIA_OTHER 0x0480
+
+#define PCI_BASE_CLASS_MEMORY 0x05
+#define PCI_CLASS_MEMORY_RAM 0x0500
+#define PCI_CLASS_MEMORY_FLASH 0x0501
+#define PCI_CLASS_MEMORY_OTHER 0x0580
+
+#define PCI_BASE_CLASS_BRIDGE 0x06
+#define PCI_CLASS_BRIDGE_HOST 0x0600
+#define PCI_CLASS_BRIDGE_ISA 0x0601
+#define PCI_CLASS_BRIDGE_EISA 0x0602
+#define PCI_CLASS_BRIDGE_MC 0x0603
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+#define PCI_CLASS_BRIDGE_PCMCIA 0x0605
+#define PCI_CLASS_BRIDGE_NUBUS 0x0606
+#define PCI_CLASS_BRIDGE_CARDBUS 0x0607
+#define PCI_CLASS_BRIDGE_OTHER 0x0680
+
+#define PCI_BASE_CLASS_COMMUNICATION 0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER 0x0780
+
+#define PCI_BASE_CLASS_SYSTEM 0x08
+#define PCI_CLASS_SYSTEM_PIC 0x0800
+#define PCI_CLASS_SYSTEM_DMA 0x0801
+#define PCI_CLASS_SYSTEM_TIMER 0x0802
+#define PCI_CLASS_SYSTEM_RTC 0x0803
+#define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+#define PCI_BASE_CLASS_INPUT 0x09
+#define PCI_CLASS_INPUT_KEYBOARD 0x0900
+#define PCI_CLASS_INPUT_PEN 0x0901
+#define PCI_CLASS_INPUT_MOUSE 0x0902
+#define PCI_CLASS_INPUT_OTHER 0x0980
+
+#define PCI_BASE_CLASS_DOCKING 0x0a
+#define PCI_CLASS_DOCKING_GENERIC 0x0a00
+#define PCI_CLASS_DOCKING_OTHER 0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR 0x0b
+#define PCI_CLASS_PROCESSOR_386 0x0b00
+#define PCI_CLASS_PROCESSOR_486 0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM 0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA 0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC 0x0b20
+#define PCI_CLASS_PROCESSOR_CO 0x0b40
+
+#define PCI_BASE_CLASS_SERIAL 0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE 0x0c00
+#define PCI_CLASS_SERIAL_ACCESS 0x0c01
+#define PCI_CLASS_SERIAL_SSA 0x0c02
+#define PCI_CLASS_SERIAL_USB 0x0c03
+#define PCI_CLASS_SERIAL_FIBER 0x0c04
+
+#define PCI_CLASS_OTHERS 0xff
+
+/* Several ID's we need in the library */
+
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_VENDOR_ID_COMPAQ 0x0e11
diff -urN flashrom-126/libpci/i386-ports.c winflashrom/libpci/i386-ports.c
--- flashrom-126/libpci/i386-ports.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/i386-ports.c 2007-08-15 14:03:34.000000000 +0200
@@ -0,0 +1,222 @@
+/*
+ * $Id: i386-ports.c,v 1.3 2002/03/30 15:39:25 mj Exp $
+ *
+ * The PCI Library -- Direct Configuration access via i386 Ports
+ *
+ * Copyright (c) 1997--1999 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+
+#include "../direct_io.h"
+#include "internal.h"
+
+/*
+ * Before we decide to use direct hardware access mechanisms, we try to do some
+ * trivial checks to ensure it at least _seems_ to be working -- we just test
+ * whether bus 00 contains a host bridge (this is similar to checking
+ * techniques used in XFree86, but ours should be more reliable since we
+ * attempt to make use of direct access hints provided by the PCI BIOS).
+ *
+ * This should be close to trivial, but it isn't, because there are buggy
+ * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
+ */
+
+static int
+intel_sanity_check(struct pci_access *a, struct pci_methods *m)
+{
+ struct pci_dev d;
+
+ a->debug("...sanity check \n");
+ d.bus = 0;
+ d.func = 0;
+ for(d.dev = 0; d.dev < 32; d.dev++)
+ {
+ u16 class, vendor;
+ if ( (m->read(&d, PCI_CLASS_DEVICE, (byte *) &class, sizeof(class)) &&
+ (class == (PCI_CLASS_BRIDGE_HOST) || class == (PCI_CLASS_DISPLAY_VGA))) ||
+ (m->read(&d, PCI_VENDOR_ID, (byte *) &vendor, sizeof(vendor)) &&
+ (vendor == (PCI_VENDOR_ID_INTEL) || vendor == (PCI_VENDOR_ID_COMPAQ))) )
+ {
+ a->debug("...outside the Asylum at 0/%02x/0 \n", d.dev);
+ return 1;
+ }
+ }
+ a->debug("...insane\n");
+ return 0;
+}
+
+/*
+ * Configuration type 1
+ */
+
+#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
+
+static int
+conf1_detect(struct pci_access *a)
+{
+ unsigned int tmp;
+ int res = 0;
+
+ outb (0x01, 0xCFB);
+ tmp = inl (0xCF8);
+ outl (0x80000000, 0xCF8);
+ if (inl (0xCF8) == 0x80000000)
+ res = 1;
+ outl (tmp, 0xCF8);
+ if (res)
+ res = intel_sanity_check(a, &pm_intel_conf1);
+ return res;
+}
+
+static int
+conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ u16 addr = 0xcfc + (pos&3);
+ outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+
+ switch (len)
+ {
+ case 1:
+ buf[0] = inb(addr);
+ break;
+ case 2:
+ ((u16 *) buf)[0] = (inw(addr));
+ break;
+ case 4:
+ ((u32 *) buf)[0] = (inl(addr));
+ break;
+ default:
+ return pci_generic_block_read(d, pos, buf, len);
+ }
+ return 1;
+}
+
+static int
+conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ u16 addr = 0xcfc + (pos&3);
+ outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
+
+ switch (len)
+ {
+ case 1:
+ outb(buf[0], addr);
+ break;
+ case 2:
+ outw((((u16 *) buf)[0]), addr);
+ break;
+ case 4:
+ outl((((u32 *) buf)[0]), addr);
+ break;
+ default:
+ return pci_generic_block_write(d, pos, buf, len);
+ }
+ return 1;
+}
+
+/*
+ * Configuration type 2. Obsolete and brain-damaged, but existing.
+ */
+
+static int
+conf2_detect(struct pci_access *a)
+{
+ /* This is ugly and tends to produce false positives. Beware. */
+
+ outb(0x00, 0xCFB);
+ outb(0x00, 0xCF8);
+ outb(0x00, 0xCFA);
+ if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00)
+ return intel_sanity_check(a, &pm_intel_conf2);
+ else
+ return 0;
+}
+
+static int
+conf2_read(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ u16 addr = 0xc000 | (d->dev << 8) | pos;
+
+ if (d->dev >= 16)
+ /* conf2 supports only 16 devices per bus */
+ return 0;
+ outb((d->func << 1) | 0xf0, 0xcf8);
+ outb((u8)d->bus, 0xcfa);
+ switch (len)
+ {
+ case 1:
+ buf[0] = inb(addr);
+ break;
+ case 2:
+ ((u16 *) buf)[0] = (inw(addr));
+ break;
+ case 4:
+ ((u32 *) buf)[0] = (inl(addr));
+ break;
+ default:
+ outb(0, 0xcf8);
+ return pci_generic_block_read(d, pos, buf, len);
+ }
+ outb(0, 0xcf8);
+ return 1;
+}
+
+static int
+conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
+{
+ u16 addr = 0xc000 | (d->dev << 8) | pos;
+
+ if (d->dev >= 16)
+ d->access->error("conf2_write: only first 16 devices exist.");
+ outb((d->func << 1) | 0xf0, 0xcf8);
+ outb((u8)d->bus, 0xcfa);
+ switch (len)
+ {
+ case 1:
+ outb(buf[0], addr);
+ break;
+ case 2:
+ outw((* (u16 *) buf), addr);
+ break;
+ case 4:
+ outl((* (u32 *) buf), addr);
+ break;
+ default:
+ outb(0, 0xcf8);
+ return pci_generic_block_write(d, pos, buf, len);
+ }
+ outb(0, 0xcf8);
+ return 1;
+}
+
+
+struct pci_methods pm_intel_conf1 = {
+ "Intel-conf1",
+ NULL, /* config */
+ conf1_detect,
+ NULL,
+ NULL,
+ pci_generic_scan,
+ pci_generic_fill_info,
+ conf1_read,
+ conf1_write,
+ NULL, /* init_dev */
+ NULL /* cleanup_dev */
+};
+
+struct pci_methods pm_intel_conf2 = {
+ "Intel-conf2",
+ NULL, /* config */
+ conf2_detect,
+ NULL,
+ NULL,
+ pci_generic_scan,
+ pci_generic_fill_info,
+ conf2_read,
+ conf2_write,
+ NULL, /* init_dev */
+ NULL /* cleanup_dev */
+};
diff -urN flashrom-126/libpci/internal.h winflashrom/libpci/internal.h
--- flashrom-126/libpci/internal.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/internal.h 2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,39 @@
+/*
+ * $Id: internal.h,v 1.7 2002/12/26 19:28:33 mj Exp $
+ *
+ * The PCI Library -- Internal Include File
+ *
+ * Copyright (c) 1997--2000 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "pci.h"
+
+struct pci_methods {
+ char *name;
+ void (*config)(struct pci_access *);
+ int (*detect)(struct pci_access *);
+ void (*init)(struct pci_access *);
+ void (*cleanup)(struct pci_access *);
+ void (*scan)(struct pci_access *);
+ int (*fill_info)(struct pci_dev *, int flags);
+ int (*read)(struct pci_dev *, int pos, byte *buf, int len);
+ int (*write)(struct pci_dev *, int pos, byte *buf, int len);
+ void (*init_dev)(struct pci_dev *);
+ void (*cleanup_dev)(struct pci_dev *);
+};
+
+void pci_generic_scan_bus(struct pci_access *, byte *busmap, word bus);
+void pci_generic_scan(struct pci_access *);
+int pci_generic_fill_info(struct pci_dev *, int flags);
+int pci_generic_block_read(struct pci_dev *, int pos, byte *buf, int len);
+int pci_generic_block_write(struct pci_dev *, int pos, byte *buf, int len);
+
+void *pci_malloc(struct pci_access *, int);
+void pci_mfree(void *);
+
+struct pci_dev *pci_alloc_dev(struct pci_access *);
+int pci_link_dev(struct pci_access *, struct pci_dev *);
+
+extern struct pci_methods pm_intel_conf1, pm_intel_conf2;
diff -urN flashrom-126/libpci/Makefile winflashrom/libpci/Makefile
--- flashrom-126/libpci/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/Makefile 2007-08-20 07:13:56.000000000 +0200
@@ -0,0 +1,27 @@
+#
+# Makefile for temporary PCI library
+#
+# by Darmawan Salihun <darmawan.salihun at gmail.com>
+#
+
+
+LIBRARY = libpci.a
+
+AR = ar
+CC = gcc
+STRIP = strip
+CFLAGS = -O2 -g -Wall -Werror
+STRIP_ARGS = -s
+
+OBJS = access.o filter.o generic.o i386-ports.o
+
+all: $(LIBRARY)
+
+$(LIBRARY): $(OBJS)
+ $(AR) -r $(LIBRARY) $(OBJS)
+
+clean:
+ rm -f *.o *~ *.a
+
+.PHONY: all clean
+
diff -urN flashrom-126/libpci/pci.h winflashrom/libpci/pci.h
--- flashrom-126/libpci/pci.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/libpci/pci.h 2007-08-15 14:03:34.000000000 +0200
@@ -0,0 +1,135 @@
+/*
+ * $Id: pci.h,v 1.12 2003/01/04 11:04:39 mj Exp $
+ *
+ * The PCI Library
+ *
+ * Copyright (c) 1997--2002 Martin Mares <mj at ucw.cz>
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _PCI_LIB_H
+#define _PCI_LIB_H
+
+#include "header.h"
+
+/*
+ * Types
+ */
+
+typedef unsigned char byte;
+typedef unsigned char u8;
+typedef unsigned short word;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+typedef unsigned long pciaddr_t;
+
+/*
+ * PCI Access Structure
+ */
+
+struct pci_methods;
+
+enum pci_access_type {
+ /* Known access methods, remember to update access.c as well */
+ PCI_ACCESS_WINDOWS_HAL, /* Windows Hardware Abstraction Layer */
+ PCI_ACCESS_I386_TYPE1, /* i386 ports, type 1 (params: none) */
+ PCI_ACCESS_I386_TYPE2, /* i386 ports, type 2 (params: none) */
+ PCI_ACCESS_MAX
+};
+
+struct pci_access {
+ /* Options you can change: */
+ unsigned int method; /* Access method */
+ char *method_params[PCI_ACCESS_MAX]; /* Parameters for the methods */
+ int buscentric; /* Bus-centric view of the world */
+
+ /* Functions you can override: */
+ void (*error)(char *msg, ...); /* Write error message and quit */
+ void (*warning)(char *msg, ...); /* Write a warning message */
+ void (*debug)(char *msg, ...); /* Write a debugging message */
+
+ struct pci_dev *devices; /* Devices found on this bus */
+
+ /* Fields used internally: */
+ struct pci_methods *methods;
+};
+
+/* Initialize PCI access */
+struct pci_access *pci_alloc(void);
+void pci_init(struct pci_access *);
+void pci_cleanup(struct pci_access *);
+
+/* Scanning of devices */
+void pci_scan_bus(struct pci_access *acc);
+struct pci_dev *pci_get_dev(struct pci_access *acc, word bus, byte dev, byte func); /* Raw access to specified device */
+void pci_free_dev(struct pci_dev *);
+
+/*
+ * Devices
+ */
+
+struct pci_dev {
+ struct pci_dev *next; /* Next device in the chain */
+ word bus; /* Higher byte can select host bridges */
+ byte dev, func; /* Device and function */
+
+ /* These fields are set by pci_fill_info() */
+ int known_fields; /* Set of info fields already known */
+ word vendor_id, device_id; /* Identity of the device */
+ int irq; /* IRQ number */
+ pciaddr_t base_addr[6]; /* Base addresses */
+ pciaddr_t size[6]; /* Region sizes */
+ pciaddr_t rom_base_addr; /* Expansion ROM base address */
+ pciaddr_t rom_size; /* Expansion ROM size */
+
+ /* Fields used internally: */
+ struct pci_access *access;
+ struct pci_methods *methods;
+ int hdrtype; /* Direct methods: header type */
+ void *aux; /* Auxillary data */
+};
+
+#define PCI_ADDR_IO_MASK (~(pciaddr_t) 0x3)
+#define PCI_ADDR_MEM_MASK (~(pciaddr_t) 0xf)
+
+byte pci_read_byte(struct pci_dev *, int pos); /* Access to configuration space */
+word pci_read_word(struct pci_dev *, int pos);
+u32 pci_read_long(struct pci_dev *, int pos);
+int pci_read_block(struct pci_dev *, int pos, byte *buf, int len);
+int pci_write_byte(struct pci_dev *, int pos, byte data);
+int pci_write_word(struct pci_dev *, int pos, word data);
+int pci_write_long(struct pci_dev *, int pos, u32 data);
+int pci_write_block(struct pci_dev *, int pos, byte *buf, int len);
+
+int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */
+
+#define PCI_FILL_IDENT 1
+#define PCI_FILL_IRQ 2
+#define PCI_FILL_BASES 4
+#define PCI_FILL_ROM_BASE 8
+#define PCI_FILL_SIZES 16
+#define PCI_FILL_RESCAN 0x10000
+
+
+/*
+ * Filters
+ */
+
+struct pci_filter {
+ int bus, slot, func; /* -1 = ANY */
+ int vendor, device;
+};
+
+void pci_filter_init(struct pci_access *, struct pci_filter *);
+int pci_filter_match(struct pci_filter *, struct pci_dev *);
+
+#define PCI_LOOKUP_VENDOR 1
+#define PCI_LOOKUP_DEVICE 2
+#define PCI_LOOKUP_CLASS 4
+#define PCI_LOOKUP_SUBSYSTEM 8
+#define PCI_LOOKUP_PROGIF 16
+#define PCI_LOOKUP_NUMERIC 0x10000
+
+#endif
diff -urN flashrom-126/m29f400bt.h winflashrom/m29f400bt.h
--- flashrom-126/m29f400bt.h 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/m29f400bt.h 2009-08-09 01:25:02.000000000 +0200
@@ -48,7 +48,7 @@
*(volatile uint8_t *)(bios + 0x555) = 0x55;
*(volatile uint8_t *)(bios + 0xAAA) = 0xA0;
- usleep(200);
+ myusec_delay(200);
}
extern __inline__ void write_page_m29f400bt(volatile uint8_t *bios,
diff -urN flashrom-126/Makefile winflashrom/Makefile
--- flashrom-126/Makefile 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/Makefile 2009-08-09 01:35:56.000000000 +0200
@@ -6,53 +6,62 @@
PROGRAM = flashrom
+RC = windres
CC = gcc
STRIP = strip
INSTALL = /usr/bin/install
PREFIX = /usr/local
+MAKE = make
#CFLAGS = -O2 -g -Wall -Werror
CFLAGS = -Os -Wall -Werror -DDISABLE_DOC # -DTS5300
-OS_ARCH = $(shell uname)
-ifeq ($(OS_ARCH), SunOS)
-LDFLAGS = -lpci -lz
-else
-LDFLAGS = -lpci -lz -static
+#OS_ARCH = $(shell uname)
+#ifeq ($(OS_ARCH), SunOS)
+#LDFLAGS = -lpci -lz
+#else
+#LDFLAGS = -lpci -lz -static
+LDFLAGS = -L./libpci -lpci -static
STRIP_ARGS = -s
-endif
+#endif
OBJS = chipset_enable.o board_enable.o udelay.o jedec.o sst28sf040.o \
am29f040b.o mx29f002.o sst39sf020.o m29f400bt.o w49f002u.o \
82802ab.o msys_doc.o pm49fl004.o sst49lf040.o sst49lfxxxc.o \
- sst_fwhub.o layout.o lbtable.o flashchips.o flashrom.o \
- sharplhf00l04.o
+ w39v040fa.o sst_fwhub.o layout.o lbtable.o flashchips.o \
+ flashrom.o sharplhf00l04.o direct_io.o error_msg.o
-all: pciutils dep $(PROGRAM)
+RESOURCES = winflashrom.rc
+RESOURCE_OBJ = winflashrom.o
+
+all: dep $(PROGRAM)
$(PROGRAM): $(OBJS)
- $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
- $(STRIP) $(STRIP_ARGS) $(PROGRAM)
+ $(RC) -o $(RESOURCE_OBJ) $(RESOURCES)
+ $(CC) -o $(PROGRAM) $(OBJS) $(RESOURCE_OBJ) $(LDFLAGS)
+ $(STRIP) $(STRIP_ARGS) $(PROGRAM).exe
clean:
- rm -f *.o *~
+ $(MAKE) -C libpci clean
+ rm -f $(PROGRAM).exe *.o *~
distclean: clean
- rm -f $(PROGRAM) .dependencies
+ rm -f $(PROGRAM).exe .dependencies
dep:
@$(CC) -MM *.c > .dependencies
+ $(MAKE) -C libpci
-pciutils:
- @echo; echo -n "Checking for pciutils and zlib... "
- @$(shell ( echo "#include <pci/pci.h>"; \
- echo "struct pci_access *pacc;"; \
- echo "int main(int argc, char **argv)"; \
- echo "{ pacc = pci_alloc(); return 0; }"; ) > .test.c )
- @$(CC) $(CFLAGS) .test.c -o .test $(LDFLAGS) &>/dev/null && \
- echo "found." || ( echo "not found."; echo; \
- echo "Please install pciutils-devel and zlib-devel."; \
- echo "See README for more information."; echo; \
- rm -f .test.c .test; exit 1)
- @rm -f .test.c .test
+#pciutils:
+# @echo; echo -n "Checking for pciutils and zlib... "
+# @$(shell ( echo "#include <pci/pci.h>"; \
+# echo "struct pci_access *pacc;"; \
+# echo "int main(int argc, char **argv)"; \
+# echo "{ pacc = pci_alloc(); return 0; }"; ) > .test.c )
+# @$(CC) $(CFLAGS) .test.c -o .test $(LDFLAGS) &>/dev/null && \
+# echo "found." || ( echo "not found."; echo; \
+# echo "Please install pciutils-devel and zlib-devel."; \
+# echo "See README for more information."; echo; \
+# rm -f .test.c .test; exit 1)
+# @rm -f .test.c .test
install: $(PROGRAM)
$(INSTALL) flashrom $(PREFIX)/bin
diff -urN flashrom-126/msys_doc.c winflashrom/msys_doc.c
--- flashrom-126/msys_doc.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/msys_doc.c 2009-08-09 01:25:00.000000000 +0200
@@ -200,7 +200,7 @@
doc_read_4nop(bios);
while (_doc_busy(bios) && (i != 0)) {
- usleep(timeout * 1000 / 20);
+ myusec_delay(timeout * 1000 / 20);
i--;
}
diff -urN flashrom-126/README winflashrom/README
--- flashrom-126/README 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/README 2009-08-09 01:25:34.000000000 +0200
@@ -1,18 +1,58 @@
-------------------------------------------------------------------------------
-Flashrom README
+Winflashrom README
-------------------------------------------------------------------------------
-This is the universal (LinuxBIOS) flash utility.
+This is the Windows port of the universal (LinuxBIOS) flash utility.
+It's named winflashrom. This code has not been merged into the LinuxBIOS
+repository. Therefore, it's available publicly only from Google Project
+hosting for a while. There are still some minor issues that prevent us
+to merge it into the LinuxBIOS repository. Anyway, you might want to
+watch LinuxBIOS mailing list
+(http://www.linuxbios.org/mailman/listinfo/linuxbios)
+for further updates on Winflashrom.
+Once a stable release of Winflashrom is available. The code in
+Google Project hosting will be updated as well.
+
Build Requirements
------------------
-To build the flashrom utility you need to have the following packages
-installed on your Linux system:
+To build the winflashrom utility you need to have the following packages
+installed on your Windows system:
-* pciutils
-* pciutils-devel / pciutils-dev
-* zlib-devel / zlib1g-dev
+* MinGW
+* MSys
+* Windows XP DDK or Windows Driver Kit (WDK). This tool is optional because the
+ package comes with a precompiled driver. However, if you want to make changes
+ to the driver source code, you will need one of them.
+* DbgView (optional). You can use this tool for remote debugging if you want to
+ try some changes to the driver code. DbgView is available from Sysinternals as
+ a freeware.
+
+How to build winflashrom from the source code
+----------------------------------------------
+* Building the application
+ To build the application, "cd" to the source code root directory of the source code
+ from within MSys (or other compatible shell that you might use) and invoke "make".
+
+* Building the driver
+ To build the driver, run the Windows XP DKK or WDK shell (The WinXP Free Build
+ environment or the WinXP Checked Build environment). Then, "cd" to the directory
+ named "driver" in the root directory of the source code and invoke "build" from
+ there. If you would like to have debugging message, use the "The WinXP checked
+ build environment" of the Windows XP DDK or WDK shell.
+
+* Remote debugging the driver
+ To do a remote debugging, first run the DbgView client in the _test machine_ by invoking
+ the following command in DbgView installation directory:
+ DbgView.exe /c /t
+
+ Then, connect to the test machine from the _remote machine_ by running DbgView.exe.
+ In the remote DbgView window, activate the Capture|Capture Kernel option,
+ Capture|Pass-Through option, and Capture|Capture Events option and
+ Disable the Capture|Capture Wind32 option as it will clutter the output with
+ unnecessary messages. Now, you can monitor the debug messages from the _test machine_.
+
Usage
@@ -179,3 +219,13 @@
VIA VT8237
VIA VT82C686
+Note on the current state of tested platform(s)
+-----------------------------------------------
+This code has been successfully tested on Pentium 4
+(single core) system with ICH5 chipset and Winbond
+W39V040FA flash chip.
+
+The driver architecture is still messy at this point.
+However, I'm working on to improve it right now and it
+should come with better code very soon.
+
diff -urN flashrom-126/sharplhf00l04.h winflashrom/sharplhf00l04.h
--- flashrom-126/sharplhf00l04.h 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/sharplhf00l04.h 2009-08-09 01:25:02.000000000 +0200
@@ -42,7 +42,8 @@
*(volatile uint8_t *)(bios + 0x2AAA) = 0x55;
*(volatile uint8_t *)(bios + 0x5555) = 0xA0;
- usleep(200);
+ //usleep(200);
+ myusec_delay(200);
}
#endif /* !__SHARPLHF00L04_H__ */
diff -urN flashrom-126/sst49lfxxxc.c winflashrom/sst49lfxxxc.c
--- flashrom-126/sst49lfxxxc.c 2009-08-09 01:28:21.000000000 +0200
+++ winflashrom/sst49lfxxxc.c 2009-08-09 01:25:00.000000000 +0200
@@ -27,7 +27,7 @@
#include <errno.h>
#include <fcntl.h>
-#include <sys/mman.h>
+//#include <sys/mman.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
diff -urN flashrom-126/todo.txt winflashrom/todo.txt
--- flashrom-126/todo.txt 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/todo.txt 2009-08-09 01:25:29.000000000 +0200
@@ -0,0 +1,11 @@
+############################################################################################
+#
+# TODO list by Darmawan Salihun 28th June 2007
+#
+#
+
+1. Code review to find logic incompatibilities.
+2. Creating diff/patch from the last modified code with regard to flashrom base code.
+
+
+
diff -urN flashrom-126/udelay.h winflashrom/udelay.h
--- flashrom-126/udelay.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/udelay.h 2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __UDELAY_H__
+#define __UDELAY_H__
+
+void myusec_delay(int time);
+
+#endif
diff -urN flashrom-126/w39v040fa.c winflashrom/w39v040fa.c
--- flashrom-126/w39v040fa.c 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/w39v040fa.c 2009-08-09 01:25:00.000000000 +0200
@@ -0,0 +1,112 @@
+/*
+ * w39v040fa.c: driver for Winbond 39V040FA flash models
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * Reference:
+ * W39V040FA data sheet
+ *
+ */
+
+#include <stdio.h>
+#include "flash.h"
+#include "jedec.h"
+#include "w39v040fa.h"
+#include "direct_io.h"
+
+enum {
+ BLOCKING_REGS_PHY_RANGE = 0x80000,
+ BLOCKING_REGS_PHY_BASE = 0xFFB80000,
+};
+
+
+static volatile char * unprotect_39v040fa(void)
+{
+ unsigned char i, byte_val;
+ volatile char * block_regs_base;
+
+ block_regs_base = (volatile char*) map_physical_addr_range( BLOCKING_REGS_PHY_BASE, BLOCKING_REGS_PHY_RANGE);
+ if (block_regs_base == NULL) {
+ perror("Error: Unable to map Winbond w39v040fa blocking registers!\n");
+ return NULL;
+ }
+
+ //
+ // Unprotect the BIOS chip address range
+ //
+ for( i = 0; i < 8 ; i++ )
+ {
+ byte_val = *(block_regs_base + 2 + i*0x10000);
+ myusec_delay(10);
+ byte_val &= 0xF8; // Enable full access to the chip
+ *(block_regs_base + 2 + i*0x10000) = byte_val;
+ myusec_delay(10);
+ }
+
+ return block_regs_base;
+}
+
+
+static void protect_39v040fa(volatile char * reg_base)
+{
+ //
+ // Protect the BIOS chip address range
+ //
+ unsigned char i, byte_val;
+ volatile char * block_regs_base = reg_base;
+
+ for( i = 0; i < 8 ; i++ )
+ {
+ byte_val = *(block_regs_base + 2 + i*0x10000);
+ myusec_delay(10);
+ byte_val |= 1; // Prohibited to write in the block where set
+ *(block_regs_base + 2 + i*0x10000) = byte_val;
+ myusec_delay(10);
+ }
+
+ unmap_physical_addr_range((void*) reg_base, BLOCKING_REGS_PHY_RANGE);
+}
+
+
+int write_39v040fa(struct flashchip *flash, uint8_t *buf)
+{
+ int i;
+ int total_size = flash->total_size * 1024;
+ int page_size = flash->page_size;
+ volatile uint8_t *bios = flash->virtual_memory;
+ volatile char * reg_base;
+
+ reg_base = unprotect_39v040fa();
+ erase_chip_jedec(flash);
+
+ printf("Programming Page: ");
+ for (i = 0; i < total_size / page_size; i++) {
+ /* write to the sector */
+ printf("%04d at address: 0x%08x", i, i * page_size);
+ write_sector_jedec(bios, buf + i * page_size,
+ bios + i * page_size, page_size);
+ printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
+ fflush(stdout);
+ }
+ printf("\n");
+
+ if(NULL != reg_base)
+ {
+ protect_39v040fa(reg_base);
+ }
+
+ return (0);
+}
diff -urN flashrom-126/w39v040fa.h winflashrom/w39v040fa.h
--- flashrom-126/w39v040fa.h 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/w39v040fa.h 2009-08-09 01:25:02.000000000 +0200
@@ -0,0 +1,6 @@
+#ifndef __W39V040FA_H__
+#define __W39V040FA_H__ 1
+
+extern int write_39v040fa(struct flashchip *flash, uint8_t *buf);
+
+#endif /* !__W39V040FA_H__ */
diff -urN flashrom-126/winflashrom.rc winflashrom/winflashrom.rc
--- flashrom-126/winflashrom.rc 1970-01-01 01:00:00.000000000 +0100
+++ winflashrom/winflashrom.rc 2007-06-28 13:10:34.000000000 +0200
@@ -0,0 +1,6 @@
+/////////////////////////////////////////////////////////////////////////
+// winflashrom resource file
+// 28 June 2007 Darmawan Salihun
+//
+
+WINFLASHROMDRV DRIVER DISCARDABLE "driver/i386/winflashrom.sys"
More information about the flashrom
mailing list