Compiler Intrinsics 的相關連結,因為最近寫C語言時常在使用所以收集此連結!
EX:
__debugbreak();
__enable();
__disable();
http://msdn.microsoft.com/zh-tw/library/26td21ds.aspx
將自己踏入BIOS領域中所學習到的知識做一些心得整理,像是Legacy BIOS、EFI BIOS、Windows Driver...etc. ※版權與智慧財產權聲明:保留所有法律權利。我在寫文章時如果有引用到其他人的地方我會盡量說明參考出處,如果有遺漏的地方請告訴我,我會馬上註明! 而轉貼我的文章時也請您註明出處!
星期二, 4月 21, 2009
星期三, 1月 21, 2009
老程式也有它的好處
大家都知道debug.com的用法,不過他還有一個應用的方式是我經常使用的!
剛好前陣子公司同事也有分享這個用法,所以就順便把他在做個簡單的介紹。
老程式Debug.com 有支援輸入/輸出導向,也就是以前DOS下的 ">" 跟"<" 符號所做的事情, 而他的用法很簡單,你只要在一個文字檔中先寫好你要做的事情,然後導入到Debug.com中 就可以了,而Debug.com就會依照你的文字檔的動作去做事情! 例如原本你使用debug.com時你做了下面的動作 -d
-q
那麼你就可以寫成一個Test.txt,然後裡面的內容是:
d
q
接著進入DOS Cmd prompt ,導入這個文字檔給debug.com 例如:
C:\> debug < test.txt
這樣子debug就會自動幫你執行d指令,還有q 離開debug.com.
而下面是一個Dump PIRQ的批次檔,我會自己去F Segment內找到'$PIR' 的位址,然後透過D指令去Dump 這個記憶體,接著把Dump的內容寫到一個檔案中:
@ECHO OFF
REM ============= Find PIRQ ===================
ECHO. s f000:0 ffff '$PIR' > FindPIRQ.txt
ECHO. q >> FindPIRQ.txt
debug <> PIRQAddr.txt
REM ============= Set variable ===================
FOR /F %%A in ('FINDSTR /C:"F000" PIRQAddr.txt') do SET FSEG=%%A
REM ============= Dump PIRQ ===================
ECHO. d %FSEG% > DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. q >> DumpPIRQ.txt
debug <> Pirq.txt
ECHO.
ECHO. Output: PIRQ.txt
ECHO.
DEL FindPIRQ.txt
DEL PIRQAddr.txt
DEL DumpPIRQ.txt
pause
底下是我產生的文字檔內的內容:
- d F000:DE80
F000:DE80 24 50 49 52 00 01 60 01-FF FF 00 00 86 80 2E 12 $PIR..`.........
F000:DE90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
F000:DEA0 00 00 00 F8 DE 00 F8 DE-00 F8 DE 00 F8 DE 00 00 ................
F000:DEB0 00 38 60 E0 1C 00 F8 DE-00 F8 DE 00 F8 DE 00 00 .8`.............
F000:DEC0 00 08 60 E0 1C 00 F8 DE-00 F8 DE 00 F8 DE 00 00 ..`.............
剛好前陣子公司同事也有分享這個用法,所以就順便把他在做個簡單的介紹。
老程式Debug.com 有支援輸入/輸出導向,也就是以前DOS下的 ">" 跟"<" 符號所做的事情, 而他的用法很簡單,你只要在一個文字檔中先寫好你要做的事情,然後導入到Debug.com中 就可以了,而Debug.com就會依照你的文字檔的動作去做事情! 例如原本你使用debug.com時你做了下面的動作 -d
-q
那麼你就可以寫成一個Test.txt,然後裡面的內容是:
d
q
接著進入DOS Cmd prompt ,導入這個文字檔給debug.com 例如:
C:\> debug < test.txt
這樣子debug就會自動幫你執行d指令,還有q 離開debug.com.
而下面是一個Dump PIRQ的批次檔,我會自己去F Segment內找到'$PIR' 的位址,然後透過D指令去Dump 這個記憶體,接著把Dump的內容寫到一個檔案中:
@ECHO OFF
REM ============= Find PIRQ ===================
ECHO. s f000:0 ffff '$PIR' > FindPIRQ.txt
ECHO. q >> FindPIRQ.txt
debug <> PIRQAddr.txt
REM ============= Set variable ===================
FOR /F %%A in ('FINDSTR /C:"F000" PIRQAddr.txt') do SET FSEG=%%A
REM ============= Dump PIRQ ===================
ECHO. d %FSEG% > DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. d >> DumpPIRQ.txt
ECHO. q >> DumpPIRQ.txt
debug <> Pirq.txt
ECHO.
ECHO. Output: PIRQ.txt
ECHO.
DEL FindPIRQ.txt
DEL PIRQAddr.txt
DEL DumpPIRQ.txt
pause
底下是我產生的文字檔內的內容:
- d F000:DE80
F000:DE80 24 50 49 52 00 01 60 01-FF FF 00 00 86 80 2E 12 $PIR..`.........
F000:DE90 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
F000:DEA0 00 00 00 F8 DE 00 F8 DE-00 F8 DE 00 F8 DE 00 00 ................
F000:DEB0 00 38 60 E0 1C 00 F8 DE-00 F8 DE 00 F8 DE 00 00 .8`.............
F000:DEC0 00 08 60 E0 1C 00 F8 DE-00 F8 DE 00 F8 DE 00 00 ..`.............
星期日, 1月 18, 2009
人生無常
『人生無常』~ 以前總覺得『無常』是無法接觸到的,是看不到摸不到的! 一旦它讓你看到/接觸到時真是令人難以承受之痛!
去年,2008.11.18 我敬愛的叔叔走了,當時很難過;一個我從小當成典範的長輩一個疼愛我的長輩離開了我,但想到他能夠自癌病中解脫,能夠到達另一個世界去未嘗不是一種新的祝福!
但人生就是如此無常,二個月後的昨天2009.01.18,我自小照顧我的奶奶因為心肌梗塞突然送進加護病房急救,在我回到苗栗時奶奶就已經走了! 最後一面沒有見到,心好痛! 在陪伴著、看著她安詳的躺在那時,淚水一直停不下來!
『人生無常』,希望大家能夠好好珍惜身邊的親友與你最愛的人! 平凡的幸福才是真正的幸福,一早起來你的親友和你愛的人能夠笑著跟你打聲招呼,這種平凡的幸福在此刻的我真的難以擁有啊!
去年,2008.11.18 我敬愛的叔叔走了,當時很難過;一個我從小當成典範的長輩一個疼愛我的長輩離開了我,但想到他能夠自癌病中解脫,能夠到達另一個世界去未嘗不是一種新的祝福!
但人生就是如此無常,二個月後的昨天2009.01.18,我自小照顧我的奶奶因為心肌梗塞突然送進加護病房急救,在我回到苗栗時奶奶就已經走了! 最後一面沒有見到,心好痛! 在陪伴著、看著她安詳的躺在那時,淚水一直停不下來!
『人生無常』,希望大家能夠好好珍惜身邊的親友與你最愛的人! 平凡的幸福才是真正的幸福,一早起來你的親友和你愛的人能夠笑著跟你打聲招呼,這種平凡的幸福在此刻的我真的難以擁有啊!
星期日, 1月 11, 2009
EFI 的新體驗~
以前在做案子的時候只管如何去把OEM/ODM features做出來,所以比較少時間去慢慢的消化EFI code的內容,其實在EFI中有很多小地方的事情是以前學C語言的時候從來都沒有注意過的事情!而這些小地方也讓我對C語言有了更進一步的體驗~
像是最近研究EFI code的過程中發現了一個好玩的東西,原來C也有類似 Strong/Weak 的寫法!
以前一直笨笨的想說C要怎麼去做這部份的東西,還一直以為做不到! 原來這些東西都已經有參考範例在EFI code之中了! 只是以前壓根子都沒想過原來C可以這樣玩~在慢慢消化EFI code的過程中還真的是驚奇不斷咧!
從最近學習EFI code的過程之中,真的讓我對C語言有了更深一層的了解;在此時回頭去想想以前自己在學校中老是以為我已經對C有一定層度的認知~現在才發現 "原來我只是個井底之蛙啊"....
像是最近研究EFI code的過程中發現了一個好玩的東西,原來C也有類似 Strong/Weak 的寫法!
以前一直笨笨的想說C要怎麼去做這部份的東西,還一直以為做不到! 原來這些東西都已經有參考範例在EFI code之中了! 只是以前壓根子都沒想過原來C可以這樣玩~在慢慢消化EFI code的過程中還真的是驚奇不斷咧!
從最近學習EFI code的過程之中,真的讓我對C語言有了更深一層的了解;在此時回頭去想想以前自己在學校中老是以為我已經對C有一定層度的認知~現在才發現 "原來我只是個井底之蛙啊"....
標籤:
EFI BIOS相關知識
星期日, 12月 28, 2008
星期二, 12月 23, 2008
SST SPI Serial Flash
今天在網路瀏覽的時候看到SST 有提供 Software Driver 的範例程式,從範例程式中可以很容易的知道如何
去控制Flash part的存取 , 如果想學R/W Flash Part的朋友可以參考看看,而底下是一個範例程式:
SST25VF080B 8 Mbit(1M x 8) Serial Flash Memory
November 4th, 2005, Rev. 1.0
ABOUT THE SOFTWARE
This application note provides software driver examples for SST25VF080B,
Serial Flash. Extensive comments are included in each routine to describe
the function of each routine. The interface coding uses polling method
rather than the SPI protocol to interface with these serial devices. The
functions are differentiated below in terms of the communication protocols
(uses Mode 0) and specific device operation instructions. This code has been
designed to compile using the Keil compiler.
ABOUT THE SST25VF080B
Companion product datasheets for the SST25VF080B should be reviewed in
conjunction with this application note for a complete understanding
of the device.
Device Communication Protocol(pinout related) functions:
Functions Function
------------------------------------------------------------------
init Initializes clock to set up mode 0.
Send_Byte Sends one byte using SI pin to send and
shift out 1-bit per clock rising edge
Get_Byte Receives one byte using SO pin to receive and shift
in 1-bit per clock falling edge
Poll_SO Used in the polling for RY/BY# of SO during AAI programming
CE_High Sets Chip Enable pin of the serial flash to high
CE_Low Clears Chip Enable of the serial flash to low
Hold_Low Clears Hold pin to make serial flash hold
Unhold Unholds the serial flash
WP_Low Clears WP pin to make serial flash write protected
UnWP Disables write protection pin
Note: The pin names of the SST25VF080B are used in this application note. The associated test code
will not compile unless these pinouts (SCK, SI, SO, SO, CE, WP, Hold) are pre-defined on your
software which should reflect your hardware interfaced.
Device Operation Instruction functions:
Functions Function
------------------------------------------------------------------
Read_Status_Register Reads the status register of the serial flash
EWSR Enables the Write Status Register
WRSR Performs a write to the status register
WREN Write enables the serial flash
WRDI Write disables the serial flash
EBSY Enable SO to output RY/BY# status during AAI programming
DBSY Disable SO to output RY/BY# status during AAI programming
Read_ID Reads the manufacturer ID and device ID
Jedec_ID_Read Reads the Jedec ID
Read Reads one byte from the serial flash and returns byte(max of 25 MHz CLK frequency)
Read_Cont Reads multiple bytes(max of 25 MHz CLK frequency)
HighSpeed_Read Reads one byte from the serial flash and returns byte(max of 50 MHz CLK frequency)
HighSpeed_Read_Cont Reads multiple bytes(max of 50 MHz CLK frequency)
Byte_Program Program one byte to the serial flash
Auto_Add_IncA Initial Auto Address Increment process
Auto_Add_IncB Successive Auto_Address_Increment process after AAI initiation
Auto_Add_IncA_EBSY Initial Auto Address Increment process with EBSY
Auto_Add_IncB_EBSY Successive Auto_Address_Increment process after AAI initiation with EBSY and WRDI/DBSY
Chip_Erase Erases entire serial flash
Sector_Erase Erases one sector (4 KB) of the serial flash
Block_Erase_32K Erases 32 KByte block memory of the serial flash
Block_Erase_64K Erases 64 KByte block memory of the serial flash
Wait_Busy Polls status register until busy bit is low
Wait_Busy_AAI Polls status register until busy bit is low for AAI programming
WREN_Check Checks to see if WEL is set
WREN_AAI_Check Checks to see if WEL and AAI mode is set
"C" LANGUAGE DRIVERS
/********************************************************************/
/* Copyright Silicon Storage Technology, Inc. (SST), 1994-2005 */
/* Example "C" language Driver of SST25VF080B Serial Flash */
/* Conrado Canio, Silicon Storage Technology, Inc. */
/* */
/* Revision 1.0, November 4th, 2005 */
/* */
/* */
/********************************************************************/
#include
#include
/* Function Prototypes */
void init();
void Send_Byte(unsigned char out);
unsigned char Get_Byte();
void Poll_SO();
void CE_High();
void CE_Low();
void Hold_Low();
void Unhold();
void WP_Low();
void UnWP();
unsigned char Read_Status_Register();
void EWSR();
void WRSR(byte);
void WREN();
void WRDI();
void EBSY();
void DBSY();
unsigned char Read_ID(ID_addr);
unsigned long Jedec_ID_Read();
unsigned char Read(unsigned long Dst);
void Read_Cont(unsigned long Dst, unsigned long no_bytes);
unsigned char HighSpeed_Read(unsigned long Dst);
void HighSpeed_Read_Cont(unsigned long Dst, unsigned long no_bytes);
void Byte_Program(unsigned long Dst, unsigned char byte);
void Auto_Add_IncA(unsigned long Dst, unsigned char byte1, unsigned char byte2);
void Auto_Add_IncB(unsigned char byte1, unsigned char byte2);
void Auto_Add_IncA_EBSY(unsigned long Dst, unsigned char byte1, unsigned char byte2);
void Auto_Add_IncB_EBSY(unsigned char byte1, unsigned char byte2);
void Chip_Erase();
void Sector_Erase(unsigned long Dst);
void Block_Erase_32K(unsigned long Dst);
void Block_Erase_64K(unsigned long Dst);
void Wait_Busy();
void Wait_Busy_AAI();
void WREN_Check();
void WREN_AAI_Check();
void Verify(unsigned char byte, unsigned char cor_byte);
unsigned char idata upper_128[128]; /* global array to store read data */
/* to upper RAM area from 80H - FFH */
/************************************************************************/
/* PROCEDURE: init */
/* */
/* This procedure initializes the SCK to low. Must be called prior to */
/* setting up mode 0. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* SCK */
/************************************************************************/
void init()
{
SCK = 0; /* set clock to low initial state */
}
/************************************************************************/
/* PROCEDURE: Send_Byte */
/* */
/* This procedure outputs a byte shifting out 1-bit per clock rising */
/* edge on the the SI pin(LSB 1st). */
/* */
/* Input: */
/* out */
/* */
/* Output: */
/* SI */
/************************************************************************/
void Send_Byte(unsigned char out)
{
unsigned char i = 0;
for (i = 0; i < 8; i++)
{
if ((out & 0x80) == 0x80) /* check if MSB is high */
SI = 1;
else
SI = 0; /* if not, set to low */
SCK = 1; /* toggle clock high */
out = (out << 1); /* shift 1 place for next bit */
SCK = 0; /* toggle clock low */
}
}
/************************************************************************/
/* PROCEDURE: Get_Byte */
/* */
/* This procedure inputs a byte shifting in 1-bit per clock falling */
/* edge on the SO pin(LSB 1st). */
/* */
/* Input: */
/* SO */
/* */
/* Output: */
/* None */
/************************************************************************/
unsigned char Get_Byte()
{
unsigned char i = 0, in = 0, temp = 0;
for (i = 0; i < 8; i++)
{
in = (in << 1); /* shift 1 place to the left or shift in 0 */
temp = SO; /* save input */
SCK = 1; /* toggle clock high */
if (temp == 1) /* check to see if bit is high */
in = in | 0x01; /* if high, make bit high */
SCK = 0; /* toggle clock low */
}
return in;
}
/************************************************************************/
/* PROCEDURE: Poll_SO */
/* */
/* This procedure polls for the SO line during AAI programming */
/* waiting for SO to transition to 1 which will indicate AAI programming*/
/* is completed */
/* */
/* Input: */
/* SO */
/* */
/* Output: */
/* None */
/************************************************************************/
void Poll_SO()
{
unsigned char temp = 0;
CE_Low();
while (temp == 0x00) /* waste time until not busy */
temp = SO;
CE_High();
}
/************************************************************************/
/* PROCEDURE: CE_High */
/* */
/* This procedure set CE = High. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* CE */
/* */
/************************************************************************/
void CE_High()
{
CE = 1; /* set CE high */
}
/************************************************************************/
/* PROCEDURE: CE_Low */
/* */
/* This procedure drives the CE of the device to low. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* CE */
/* */
/************************************************************************/
void CE_Low()
{
CE = 0; /* clear CE low */
}
/************************************************************************/
/* PROCEDURE: Hold() */
/* */
/* This procedure clears the Hold pin to low. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* Hold */
/************************************************************************/
void Hold_Low()
{
Hold = 0; /* clear Hold pin */
}
/************************************************************************/
/* PROCEDURE: Unhold() */
/* */
/* This procedure sets the Hold pin to high. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* Hold */
/************************************************************************/
void Unhold()
{
Hold = 1; /* set Hold pin */
}
/************************************************************************/
/* PROCEDURE: WP() */
/* */
/* This procedure clears the WP pin to low. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* WP */
/************************************************************************/
void WP_Low()
{
WP = 0; /* clear WP pin */
}
/************************************************************************/
/* PROCEDURE: UnWP() */
/* */
/* This procedure sets the WP pin to high. */
/* */
/* Input: */
/* None */
/* */
/* Output: */
/* WP */
/************************************************************************/
void UnWP()
{
WP = 1; /* set WP pin */
}
/************************************************************************/
/* PROCEDURE: Read_Status_Register */
/* */
/* This procedure read the status register and returns the byte. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* byte */
/************************************************************************/
unsigned char Read_Status_Register()
{
unsigned char byte = 0;
CE_Low(); /* enable device */
Send_Byte(0x05); /* send RDSR command */
byte = Get_Byte(); /* receive byte */
CE_High(); /* disable device */
return byte;
}
/************************************************************************/
/* PROCEDURE: EWSR */
/* */
/* This procedure Enables Write Status Register. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void EWSR()
{
CE_Low(); /* enable device */
Send_Byte(0x50); /* enable writing to the status register */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: WRSR */
/* */
/* This procedure writes a byte to the Status Register. */
/* */
/* Input: */
/* byte */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WRSR(byte)
{
CE_Low(); /* enable device */
Send_Byte(0x01); /* select write to status register */
Send_Byte(byte); /* data that will change the status of BPx
or BPL (only bits 2,3,4,5,7 can be written) */
CE_High(); /* disable the device */
}
/************************************************************************/
/* PROCEDURE: WREN */
/* */
/* This procedure enables the Write Enable Latch. It can also be used */
/* to Enables Write Status Register. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WREN()
{
CE_Low(); /* enable device */
Send_Byte(0x06); /* send WREN command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: WRDI */
/* */
/* This procedure disables the Write Enable Latch. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WRDI()
{
CE_Low(); /* enable device */
Send_Byte(0x04); /* send WRDI command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: EBSY */
/* */
/* This procedure enable SO to output RY/BY# status during AAI */
/* programming. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void EBSY()
{
CE_Low(); /* enable device */
Send_Byte(0x70); /* send EBSY command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: DBSY */
/* */
/* This procedure disable SO as output RY/BY# status signal during AAI */
/* programming. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void DBSY()
{
CE_Low(); /* enable device */
Send_Byte(0x80); /* send DBSY command */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Read_ID */
/* */
/* This procedure Reads the manufacturer's ID and device ID. It will */
/* use 90h or ABh as the command to read the ID (90h in this sample). */
/* It is up to the user to give the last byte ID_addr to determine */
/* whether the device outputs manufacturer's ID first, or device ID */
/* first. Please see the product datasheet for details. Returns ID in */
/* variable byte. */
/* */
/* Input: */
/* ID_addr */
/* */
/* Returns: */
/* byte: ID1(Manufacture's ID = BFh or Device ID = 8Eh) */
/* */
/************************************************************************/
unsigned char Read_ID(ID_addr)
{
unsigned char byte;
CE_Low(); /* enable device */
Send_Byte(0x90); /* send read ID command (90h or ABh) */
Send_Byte(0x00); /* send address */
Send_Byte(0x00); /* send address */
Send_Byte(ID_addr); /* send address - either 00H or 01H */
byte = Get_Byte(); /* receive byte */
CE_High(); /* disable device */
return byte;
}
/************************************************************************/
/* PROCEDURE: Jedec_ID_Read */
/* */
/* This procedure Reads the manufacturer's ID (BFh), memory type (25h) */
/* and device ID (8Eh). It will use 9Fh as the JEDEC ID command. */
/* Please see the product datasheet for details. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* IDs_Read:ID1(Manufacture's ID = BFh, Memory Type (25h), */
/* and Device ID (8Eh) */
/* */
/************************************************************************/
unsigned long Jedec_ID_Read()
{
unsigned long temp;
temp = 0;
CE_Low(); /* enable device */
Send_Byte(0x9F); /* send JEDEC ID command (9Fh) */
temp = (temp | Get_Byte()) << 8; /* receive byte */
temp = (temp | Get_Byte()) << 8;
temp = (temp | Get_Byte()); /* temp value = 0xBF258E */
CE_High(); /* disable device */
return temp;
}
/************************************************************************/
/* PROCEDURE: Read */
/* */
/* This procedure reads one address of the device. It will return the */
/* byte read in variable byte. */
/* */
/* */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* */
/* */
/* Returns: */
/* byte */
/* */
/************************************************************************/
unsigned char Read(unsigned long Dst)
{
unsigned char byte = 0;
CE_Low(); /* enable device */
Send_Byte(0x03); /* read command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
byte = Get_Byte();
CE_High(); /* disable device */
return byte; /* return one byte read */
}
/************************************************************************/
/* PROCEDURE: Read_Cont */
/* */
/* This procedure reads multiple addresses of the device and stores */
/* data into 128 byte buffer. Maximum byte that can be read is 128 bytes*/
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* no_bytes Number of bytes to read (max = 128) */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Read_Cont(unsigned long Dst, unsigned long no_bytes)
{
unsigned long i = 0;
CE_Low(); /* enable device */
Send_Byte(0x03); /* read command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
for (i = 0; i < no_bytes; i++) /* read until no_bytes is reached */
{
upper_128[i] = Get_Byte(); /* receive byte and store at address 80H - FFH */
}
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: HighSpeed_Read */
/* */
/* This procedure reads one address of the device. It will return the */
/* byte read in variable byte. */
/* */
/* */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* */
/* */
/* Returns: */
/* byte */
/* */
/************************************************************************/
unsigned char HighSpeed_Read(unsigned long Dst)
{
unsigned char byte = 0;
CE_Low(); /* enable device */
Send_Byte(0x0B); /* read command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(0xFF); /*dummy byte*/
byte = Get_Byte();
CE_High(); /* disable device */
return byte; /* return one byte read */
}
/************************************************************************/
/* PROCEDURE: HighSpeed_Read_Cont */
/* */
/* This procedure reads multiple addresses of the device and stores */
/* data into 128 byte buffer. Maximum byte that can be read is 128 bytes*/
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* no_bytes Number of bytes to read (max = 128) */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void HighSpeed_Read_Cont(unsigned long Dst, unsigned long no_bytes)
{
unsigned long i = 0;
CE_Low(); /* enable device */
Send_Byte(0x0B); /* read command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(0xFF); /*dummy byte*/
for (i = 0; i < no_bytes; i++) /* read until no_bytes is reached */
{
upper_128[i] = Get_Byte(); /* receive byte and store at address 80H - FFH */
}
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Byte_Program */
/* */
/* This procedure programs one address of the device. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* byte: byte to be programmed */
/* */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Byte_Program(unsigned long Dst, unsigned char byte)
{
CE_Low(); /* enable device */
Send_Byte(0x02); /* send Byte Program command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(byte); /* send byte to be programmed */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Auto_Add_IncA */
/* */
/* This procedure programs consecutive addresses of 2 bytes of data into*/
/* the device: 1st data byte will be programmed into the initial */
/* address [A23-A1] and with A0 = 0. The 2nd data byte will be be */
/* programmed into initial address [A23-A1] and with A0 = 1. This */
/* is used to to start the AAI process. It should be followed by */
/* Auto_Add_IncB. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* */
/* Note: Only RDSR command can be executed once in AAI mode with SO */
/* disable to output RY/BY# status. Use WRDI to exit AAI mode */
/* unless AAI is programming the last address or last address of */
/* unprotected block, which automatically exits AAI mode. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* byte1: 1st byte to be programmed */
/* byte1: 2nd byte to be programmed */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Auto_Add_IncA(unsigned long Dst, unsigned char byte1, unsigned char byte2)
{
CE_Low(); /* enable device */
Send_Byte(0xAD); /* send AAI command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(byte1); /* send 1st byte to be programmed */
Send_Byte(byte2); /* send 2nd byte to be programmed */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Auto_Add_IncB */
/* */
/* This procedure programs consecutive addresses of 2 bytes of data into*/
/* the device: 1st data byte will be programmed into the initial */
/* address [A23-A1] and with A0 = 0. The 2nd data byte will be be */
/* programmed into initial address [A23-A1] and with A0 = 1. This */
/* is used after Auto_Address_IncA. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* Note: Only WRDI and AAI command can be executed once in AAI mode */
/* with SO enabled as RY/BY# status. When the device is busy */
/* asserting CE# will output the status of RY/BY# on SO. Use WRDI */
/* to exit AAI mode unless AAI is programming the last address or */
/* last address of unprotected block, which automatically exits */
/* AAI mode. */
/* */
/* Input: */
/* */
/* byte1: 1st byte to be programmed */
/* byte2: 2nd byte to be programmed */
/* */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Auto_Add_IncB(unsigned char byte1, unsigned char byte2)
{
CE_Low(); /* enable device */
Send_Byte(0xAD); /* send AAI command */
Send_Byte(byte1); /* send 1st byte to be programmed */
Send_Byte(byte2); /* send 2nd byte to be programmed */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Auto_Add_IncA_EBSY */
/* */
/* This procedure is the same as procedure Auto_Add_IncA except that it */
/* uses EBSY and Poll_SO functions to check for RY/BY. It programs */
/* consecutive addresses of the device. The 1st data byte will be */
/* programmed into the initial address [A23-A1] and with A0 = 0. The */
/* 2nd data byte will be programmed into initial address [A23-A1] and */
/* with A0 = 1. This is used to to start the AAI process. It should */
/* be followed by Auto_Add_IncB_EBSY. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* */
/* Note: Only WRDI and AAI command can be executed once in AAI mode */
/* with SO enabled as RY/BY# status. When the device is busy */
/* asserting CE# will output the status of RY/BY# on SO. Use WRDI */
/* to exit AAI mode unless AAI is programming the last address or */
/* last address of unprotected block, which automatically exits */
/* AAI mode. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* byte1: 1st byte to be programmed */
/* byte1: 2nd byte to be programmed */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Auto_Add_IncA_EBSY(unsigned long Dst, unsigned char byte1, unsigned char byte2)
{
EBSY(); /* enable RY/BY# status for SO in AAI */
CE_Low(); /* enable device */
Send_Byte(0xAD); /* send AAI command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
Send_Byte(byte1); /* send 1st byte to be programmed */
Send_Byte(byte2); /* send 2nd byte to be programmed */
CE_High(); /* disable device */
Poll_SO(); /* polls RY/BY# using SO line */
}
/************************************************************************/
/* PROCEDURE: Auto_Add_IncB_EBSY */
/* */
/* This procedure is the same as Auto_Add_IncB except that it uses */
/* Poll_SO to poll for RY/BY#. It demonstrate on how to use DBSY after */
/* AAI programmming is completed. It programs consecutive addresses of */
/* the device. The 1st data byte will be programmed into the initial */
/* address [A23-A1] and with A0 = 0. The 2nd data byte will be */
/* programmed into initial address [A23-A1] and with A0 = 1. This is */
/* used after Auto_Address_IncA. */
/* Assumption: Address being programmed is already erased and is NOT */
/* block protected. */
/* */
/* Note: Only WRDI and AAI command can be executed once in AAI mode */
/* with SO enabled as RY/BY# status. When the device is busy, */
/* asserting CE# will output the status of RY/BY# on SO. Use WRDI */
/* to exit AAI mode unless AAI is programming the last address or */
/* last address of unprotected block, which automatically exits */
/* AAI mode. */
/* */
/* Input: */
/* */
/* byte1: 1st byte to be programmed */
/* byte2: 2nd byte to be programmed */
/* */
/* */
/* Returns: */
/* Nothing */
/* */
/************************************************************************/
void Auto_Add_IncB_EBSY(unsigned char byte1, unsigned char byte2)
{
CE_Low(); /* enable device */
Send_Byte(0xAD); /* send AAI command */
Send_Byte(byte1); /* send 1st byte to be programmed */
Send_Byte(byte2); /* send 2nd byte to be programmed */
CE_High(); /* disable device */
Poll_SO(); /* polls RY/BY# using SO line */
WRDI(); /* Exit AAI before executing DBSY */
DBSY(); /* disable SO as RY/BY# output if in AAI */
}
/************************************************************************/
/* PROCEDURE: Chip_Erase */
/* */
/* This procedure erases the entire Chip. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Chip_Erase()
{
CE_Low(); /* enable device */
Send_Byte(0x60); /* send Chip Erase command (60h or C7h) */
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Sector_Erase */
/* */
/* This procedure Sector Erases the Chip. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Sector_Erase(unsigned long Dst)
{
CE_Low(); /* enable device */
Send_Byte(0x20); /* send Sector Erase command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Block_Erase_32K */
/* */
/* This procedure Block Erases 32 KByte of the Chip. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Block_Erase_32K(unsigned long Dst)
{
CE_Low(); /* enable device */
Send_Byte(0x52); /* send 32 KByte Block Erase command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Block_Erase_64K */
/* */
/* This procedure Block Erases 64 KByte of the Chip. */
/* */
/* Input: */
/* Dst: Destination Address 000000H - 0FFFFFH */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Block_Erase_64K(unsigned long Dst)
{
CE_Low(); /* enable device */
Send_Byte(0xD8); /* send 64KByte Block Erase command */
Send_Byte(((Dst & 0xFFFFFF) >> 16)); /* send 3 address bytes */
Send_Byte(((Dst & 0xFFFF) >> 8));
Send_Byte(Dst & 0xFF);
CE_High(); /* disable device */
}
/************************************************************************/
/* PROCEDURE: Wait_Busy */
/* */
/* This procedure waits until device is no longer busy (can be used by */
/* Byte-Program, Sector-Erase, Block-Erase, Chip-Erase). */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Wait_Busy()
{
while (Read_Status_Register() == 0x03) /* waste time until not busy */
Read_Status_Register();
}
/************************************************************************/
/* PROCEDURE: Wait_Busy_AAI */
/* */
/* This procedure waits until device is no longer busy for AAI mode. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Wait_Busy_AAI()
{
while (Read_Status_Register() == 0x43) /* waste time until not busy */
Read_Status_Register();
}
/************************************************************************/
/* PROCEDURE: WREN_Check */
/* */
/* This procedure checks to see if WEL bit set before program/erase. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WREN_Check()
{
unsigned char byte;
byte = Read_Status_Register(); /* read the status register */
if (byte != 0x02) /* verify that WEL bit is set */
{
while(1)
/* add source code or statements for this file */
/* to compile */
/* i.e. option: insert a display to view error on LED? */
}
}
/************************************************************************/
/* PROCEDURE: WREN_AAI_Check */
/* */
/* This procedure checks for AAI and WEL bit once in AAI mode. */
/* */
/* Input: */
/* None */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void WREN_AAI_Check()
{
unsigned char byte;
byte = Read_Status_Register(); /* read the status register */
if (byte != 0x42) /* verify that AAI and WEL bit is set */
{
while(1)
/* add source code or statements for this file */
/* to compile */
/* i.e. option: insert a display to view error on LED? */
}
}
/************************************************************************/
/* PROCEDURE: Verify */
/* */
/* This procedure checks to see if the correct byte has be read. */
/* */
/* Input: */
/* byte: byte read */
/* cor_byte: correct_byte that should be read */
/* */
/* Returns: */
/* Nothing */
/************************************************************************/
void Verify(unsigned char byte, unsigned char cor_byte)
{
if (byte != cor_byte)
{
while(1)
/* add source code or statement for this file */
/* to compile */
/* i.e. option: insert a display to view error on LED? */
}
}
int main()
{
return 0;
}
而範例程式中已經把主要的控制方式的"概念"都已經列出來了!
所以只要讀一下Datasheet應該就可以了解他的意義!
至於main()裡面要做甚麼就因人而異,因此千萬不要問我 main()要怎麼寫!
Reference
http://www.sst.com
點Software Driver 旁邊的TXT就可以看到範例程式
星期六, 12月 13, 2008
網友Joey的網站
今天收到一位網友Joey的來信,來信中分享了他的網站以及他的作品!
在瀏覽過他的網站與作品後,看到他對自己的作品有所堅持並且加入自己的巧思與創新,然後開發出不一樣感覺的工具! 真是深深的佩服他!
看到他這麼努力的研究,就更感覺自己太懶惰了! 以前為了寫程式廢寢忘食的我去了哪裡呢?!
我自己也要反省一下了>.<... 以下是他的作品之一的簡介,如果有興趣的朋友可以去他的網站下載:
Mini OSW 是全世界最小的多重開機程式,只有 396 Bytes,
如果你原本有使用其它的多重開機程式,
也可以很快的使用 MiniOSW 替代。
可說是,麻雀雖小,五臟俱全。
Joey 的網站:
http://chizone.miroko.tw/
在瀏覽過他的網站與作品後,看到他對自己的作品有所堅持並且加入自己的巧思與創新,然後開發出不一樣感覺的工具! 真是深深的佩服他!
看到他這麼努力的研究,就更感覺自己太懶惰了! 以前為了寫程式廢寢忘食的我去了哪裡呢?!
我自己也要反省一下了>.<... 以下是他的作品之一的簡介,如果有興趣的朋友可以去他的網站下載:
Mini OSW 是全世界最小的多重開機程式,只有 396 Bytes,
如果你原本有使用其它的多重開機程式,
也可以很快的使用 MiniOSW 替代。
可說是,麻雀雖小,五臟俱全。
Joey 的網站:
http://chizone.miroko.tw/
星期日, 12月 07, 2008
MRT v.s Microsoft® Windows® 惡意軟體移除工具
MRT ?? 不是指我們的捷運 Metropolitan Rapid Transit(M.R.T 大都會捷運系統)!
一般如果你有安裝正版的Vista 或是XP , 而且有開啟自動更新功能時,你會發現他會自動下載一個叫做Microsoft® Windows® 惡意軟體移除工具的軟體! 當他安裝好之後你卻不曾看過他執行!
要如何使用微軟提供的這的工具呢?
很簡單,你只要到 開始->執行 ,然後鍵入"MRT"後按下確定,那麼這個工具就會被你叫出來執行了!
一般如果你有安裝正版的Vista 或是XP , 而且有開啟自動更新功能時,你會發現他會自動下載一個叫做Microsoft® Windows® 惡意軟體移除工具的軟體! 當他安裝好之後你卻不曾看過他執行!
要如何使用微軟提供的這的工具呢?
很簡單,你只要到 開始->執行 ,然後鍵入"MRT"後按下確定,那麼這個工具就會被你叫出來執行了!
星期一, 11月 03, 2008
VS2005 Debugger
最近在學習使用VS2005環境,慢慢熟悉一些介面以及開啟專案...etc.
而這個過程中遇到了一個很基本的問題,害我突然腦袋空白了一陣子.....>.< 這個問題是在Debugger 一個程式碼的時候遇到的... 一般我們C語言中的進入點假設寫成這樣: int main ( int Argc, INT8 *Argv[] ) 我很直覺就是按下F5 開始Debugger ...但是今天突然間要在command line 放一些引數後再讓我的Debugger可以開始Trace code... 於是我腦袋突然空白了...VS2005 要在哪邊設定 ...冏 我在Debugger的Code是EFI的ProcessDSC , 因為平常都是在MakeFile設定,command line , 所以要拿來用Debuuger追code 還真的讓我不知所措了一陣子. 不過後來找到了VS2005設定的地方,也順利的可以繼續往下追了! 這個問題也就解決了! 這邊就把我找到的設定地方做個筆記,方便自己以後可以查閱! 下圖是VS2005 --> Property Page --> Configuration Properties --> Debuggung 的設定
只要在Command Arguments 填入要設定的引數,然後按下F5時就可以帶進去了!
下圖是Debugger中下斷點時可以看到Argv[1]是我設定的引數:
而這個過程中遇到了一個很基本的問題,害我突然腦袋空白了一陣子.....>.< 這個問題是在Debugger 一個程式碼的時候遇到的... 一般我們C語言中的進入點假設寫成這樣: int main ( int Argc, INT8 *Argv[] ) 我很直覺就是按下F5 開始Debugger ...但是今天突然間要在command line 放一些引數後再讓我的Debugger可以開始Trace code... 於是我腦袋突然空白了...VS2005 要在哪邊設定 ...冏 我在Debugger的Code是EFI的ProcessDSC , 因為平常都是在MakeFile設定,command line , 所以要拿來用Debuuger追code 還真的讓我不知所措了一陣子. 不過後來找到了VS2005設定的地方,也順利的可以繼續往下追了! 這個問題也就解決了! 這邊就把我找到的設定地方做個筆記,方便自己以後可以查閱! 下圖是VS2005 --> Property Page --> Configuration Properties --> Debuggung 的設定
只要在Command Arguments 填入要設定的引數,然後按下F5時就可以帶進去了!
標籤:
Windows 程式相關
星期一, 10月 06, 2008
ACPIView for both vista and XP
感謝網友nickel授權,我把ACPI view 放在我的部落格給有需要的人下載!
這個版本只能列舉,所以功能有些限制,如果需要更多資訊的人請聯絡nickel,,他應該會給大家更仔細的說明!
點我下載ACPIView for both vista&XP
這個版本只能列舉,所以功能有些限制,如果需要更多資訊的人請聯絡nickel,,他應該會給大家更仔細的說明!
點我下載ACPIView for both vista&XP
星期二, 9月 30, 2008
JR! Sean Kingston! Beautiful girl
最近請小洋開車幫我搬家,在他車上聽到這首歌,感覺還不錯所以就去找了歌詞回來聽~
因為還不錯聽,所以就順便把歌詞放在Blog分享一下~~~
【JR! Sean Kingston! Beautiful girl】
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it’s over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They'll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it’s over
當她們說一切結束了
See it started at the park
記得我們那是在一個公園的黃昏
Used to chill at the dark
當時的晚風有些冷凜
Oh when you took my heart
哦 當你帶走了我的心
That's when we fell apart
我們迷失了自己
Coz we both thought
因為我們都認為
That love lasts forever (lasts forever)
愛會永恆(永恆)
They say we're too young
人們都說我們太過年輕
To get ourselves sprung
太易衝動
Oh we didn't care
哦 我們不曾在乎
We made it very clear
我們也都明瞭清楚
And they also said
他們甚至說
That we couldn't last together (last together)
說我們不會長久(長久)
See it's very define, girl
女孩 這不用置疑
One of a kind
你是那樣的無與倫比
But you mush up my mind
而你讓我意亂情迷
You walk to get declined
卻讓我們的愛衰逝
Oh Lord…
哦 老天
My baby is driving me crazy
你真的讓令我發瘋發癲
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it's over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They'll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it's over
當她們說一切結束了
It was back in '99
回想九九的那一年
Watchin' movies all the time
除了看電影整日無所事事
Oh when I went away
哦 那時我還懵懂
For doin' my first crime
還做些偷雞摸狗的混事
And I never thought
但我從沒想過
That we was gonna see each other (see each other)
那天的碰面你我會一見鍾情(一見鍾情)
And then I came out
於是我混沌初開
Mami moved me down South
媽咪雖帶我去了南方
Oh I'm with my girl
哦 可我卻整日想著我的女孩
Who I thought was my world
因為我以為她就是我的世界
It came out to be
可結果是
That she wasn't the girl for me (girl for me)
她卻離我而去(而去)
See it's very define, girl
女孩 這不用置疑
One of a kind
你是那樣的無與倫比
But you mush up my mind
而你讓我意亂情迷
You walk to get declined
卻讓我們的愛衰逝
Oh Lord…
哦 老天
My baby is driving me crazy
你真的讓令我發瘋發癲
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it’s over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They’ll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it's over
當她們說一切結束了
Now we're fussin’
現在我們的焦躁
And now we're fightin’
我們在掙扎
Please tell me why
請告訴我為什麼
I'm feelin' slightin'
我是那樣的無望
And I don't know
我不知道
How to make it better (make it better)
該怎麼來彌補(彌補)
You're datin' other guys
你想著其他男人
You're tellin' me lies
還對我謊話連篇
Oh I can't believe
哦 我不敢相信
What I'm seein' with my eyes
可我親眼所見
I'm losin' my mind
從此迷失心智
And I don't think it's clever (think it's clever)
雖然我知道這並不明智(並不明智)
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal, suicidal
你在令我走向毀滅 毀滅 毀滅 ....
因為還不錯聽,所以就順便把歌詞放在Blog分享一下~~~
【JR! Sean Kingston! Beautiful girl】
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it’s over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They'll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it’s over
當她們說一切結束了
See it started at the park
記得我們那是在一個公園的黃昏
Used to chill at the dark
當時的晚風有些冷凜
Oh when you took my heart
哦 當你帶走了我的心
That's when we fell apart
我們迷失了自己
Coz we both thought
因為我們都認為
That love lasts forever (lasts forever)
愛會永恆(永恆)
They say we're too young
人們都說我們太過年輕
To get ourselves sprung
太易衝動
Oh we didn't care
哦 我們不曾在乎
We made it very clear
我們也都明瞭清楚
And they also said
他們甚至說
That we couldn't last together (last together)
說我們不會長久(長久)
See it's very define, girl
女孩 這不用置疑
One of a kind
你是那樣的無與倫比
But you mush up my mind
而你讓我意亂情迷
You walk to get declined
卻讓我們的愛衰逝
Oh Lord…
哦 老天
My baby is driving me crazy
你真的讓令我發瘋發癲
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it's over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They'll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it's over
當她們說一切結束了
It was back in '99
回想九九的那一年
Watchin' movies all the time
除了看電影整日無所事事
Oh when I went away
哦 那時我還懵懂
For doin' my first crime
還做些偷雞摸狗的混事
And I never thought
但我從沒想過
That we was gonna see each other (see each other)
那天的碰面你我會一見鍾情(一見鍾情)
And then I came out
於是我混沌初開
Mami moved me down South
媽咪雖帶我去了南方
Oh I'm with my girl
哦 可我卻整日想著我的女孩
Who I thought was my world
因為我以為她就是我的世界
It came out to be
可結果是
That she wasn't the girl for me (girl for me)
她卻離我而去(而去)
See it's very define, girl
女孩 這不用置疑
One of a kind
你是那樣的無與倫比
But you mush up my mind
而你讓我意亂情迷
You walk to get declined
卻讓我們的愛衰逝
Oh Lord…
哦 老天
My baby is driving me crazy
你真的讓令我發瘋發癲
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal
你在令我走向毀滅 毀滅
When you say it’s over
當你說我們緣分到此為至
Damn all these beautiful girls
這些可恨的美女
They only wanna do your dirt
她們只想挑出妳的是是非非
They’ll have you suicidal, suicidal
她們也想讓你走向毀滅 毀滅
When they say it's over
當她們說一切結束了
Now we're fussin’
現在我們的焦躁
And now we're fightin’
我們在掙扎
Please tell me why
請告訴我為什麼
I'm feelin' slightin'
我是那樣的無望
And I don't know
我不知道
How to make it better (make it better)
該怎麼來彌補(彌補)
You're datin' other guys
你想著其他男人
You're tellin' me lies
還對我謊話連篇
Oh I can't believe
哦 我不敢相信
What I'm seein' with my eyes
可我親眼所見
I'm losin' my mind
從此迷失心智
And I don't think it's clever (think it's clever)
雖然我知道這並不明智(並不明智)
You're way too beautiful girl
女孩,妳過於的完美
That's why it'll never work
這就是為何我們的愛情始終沒有結局
You'll have me suicidal, suicidal, suicidal
你在令我走向毀滅 毀滅 毀滅 ....
星期三, 9月 10, 2008
BIOS 輔助工具
很多朋友在問我, BIOS工程師一般都會拿哪些工具去輔助?!
這邊我就列出幾個比較看到的工具給大家參考一下:
DOS
● RU.EXE - AMI 公司的一個工具,可以在dos下查看硬體資訊, 從原作者網站得到的資訊如下:
1. PCI configuration space
2. PCI Express
3. Super I/O chipsets
4. System chipsets
5. 16bit port read/write up to 32bit data
6. IO space
7. IDE data returned by Identify Command
8. Up to 4GB memory read/write (In EMM386/Windows 9x max=1MB)
9. CPU MSRs
10. SMBIOS data
11. SMBUS data
●Debug.com - DOS自帶的工具,可以簡易的輔助你反組譯程式碼
●Debug32.exe - Quantasm Corp. 出版的工具,同Debug.com但是可以查看 32 bit Register.
Windows
●SE.EXE - 同RU.EXE功能,Windows版本!
●RW-Everything - 同SE.EXE 視窗版,之前PCIE BaseAddr會讀取錯誤現在不知道改好了沒?!
●AcpiView - Microsoft for Windows 2000/XP ,可查看ACPI Table
●AcpiViewVista - 網友nickel 寫的,同AcpiView 可在Vista下查看ACPI Table
●ACPIScope - 同ACPI view功能,可查看ACPI Table
●DMIScope - 可查看DMI Table
●PCIScope - 可查看PCI/PCIE Info
●Key101.exe - 我T學長的以前同事key寫的(目前人還在我們公司某NB單位),功能同SE.EXE 但針對P公司BIOS撰寫!所以可讀取一些BIOS資訊!
●USBView.exe - 可列舉USB 設備在哪些Controller上.
以上工具的介紹可在下面網站下載或是得到相關資訊,至於相關版權問題請自行與作者洽詢!
Reference
http://ruexe.blogspot.com/
http://rweverything.phpnet.us/
http://www.tssc.de/index.htm
http://www.programmer-club.com
這邊我就列出幾個比較看到的工具給大家參考一下:
DOS
● RU.EXE - AMI 公司的一個工具,可以在dos下查看硬體資訊, 從原作者網站得到的資訊如下:
1. PCI configuration space
2. PCI Express
3. Super I/O chipsets
4. System chipsets
5. 16bit port read/write up to 32bit data
6. IO space
7. IDE data returned by Identify Command
8. Up to 4GB memory read/write (In EMM386/Windows 9x max=1MB)
9. CPU MSRs
10. SMBIOS data
11. SMBUS data
●Debug.com - DOS自帶的工具,可以簡易的輔助你反組譯程式碼
●Debug32.exe - Quantasm Corp. 出版的工具,同Debug.com但是可以查看 32 bit Register.
Windows
●SE.EXE - 同RU.EXE功能,Windows版本!
●RW-Everything - 同SE.EXE 視窗版,之前PCIE BaseAddr會讀取錯誤現在不知道改好了沒?!
●AcpiView - Microsoft for Windows 2000/XP ,可查看ACPI Table
●AcpiViewVista - 網友nickel 寫的,同AcpiView 可在Vista下查看ACPI Table
●ACPIScope - 同ACPI view功能,可查看ACPI Table
●DMIScope - 可查看DMI Table
●PCIScope - 可查看PCI/PCIE Info
●Key101.exe - 我T學長的以前同事key寫的(目前人還在我們公司某NB單位),功能同SE.EXE 但針對P公司BIOS撰寫!所以可讀取一些BIOS資訊!
●USBView.exe - 可列舉USB 設備在哪些Controller上.
以上工具的介紹可在下面網站下載或是得到相關資訊,至於相關版權問題請自行與作者洽詢!
Reference
http://ruexe.blogspot.com/
http://rweverything.phpnet.us/
http://www.tssc.de/index.htm
http://www.programmer-club.com
星期三, 9月 03, 2008
星期日, 8月 17, 2008
WinSAT
最近幫中華隊加油,真是越看越生氣! 今天早上看新聞還看到我們還有機會爭第六名,還一堆記者很高興的寫文章安慰自己,真是曾幾何時我們的棒球淪落到只能拿第六名!
但無論中華隊這次表現如何,他們代表著我們奮戰的精神! 畢竟比賽還沒結束,還是要奮戰到底!
創造另一個奇蹟吧,中華隊!!!
加油歸加油,今天要提到的主題是Vista 6001(SP1)下的一些內建工具中ㄧ個很實用的工具,他的名字叫做"WinSAT"
這個工具內建在Vista之中,你可以先開啟一個管理者權限的cmd,然後直接鍵入WinSAT後就可以執行,不過執行的時候有內建一些參數,所以你必須選擇你要的功能。
而這個工具有什麼用途呢? 這個工具可以當作是Benchmark 工具,用來測試你的系統! 像是CPU/Graphic ...等都可以拿來測試!
因為他是微軟內建的工具,所以由微軟的網站上可以得到相關的使用說明,請參閱下面連結:
詳細的WinSAT使用方式
由上面的連結中,你可以發現其他的內建工具的用法,找找看,或許你會發現更好玩的東西喔!
幾個測試範例:
1. WinSAT cpu d3d -objs C(20) -texshader -totalobj 100 -time 60 -v -compression
2.WinSAT cpu aurora -time 120 -v -encryption
3.WinSAT d3d -texshader -totalobj 300 -time 120 -v
Reference
http://technet.microsoft.com
但無論中華隊這次表現如何,他們代表著我們奮戰的精神! 畢竟比賽還沒結束,還是要奮戰到底!
創造另一個奇蹟吧,中華隊!!!
加油歸加油,今天要提到的主題是Vista 6001(SP1)下的一些內建工具中ㄧ個很實用的工具,他的名字叫做"WinSAT"
這個工具內建在Vista之中,你可以先開啟一個管理者權限的cmd,然後直接鍵入WinSAT後就可以執行,不過執行的時候有內建一些參數,所以你必須選擇你要的功能。
而這個工具有什麼用途呢? 這個工具可以當作是Benchmark 工具,用來測試你的系統! 像是CPU/Graphic ...等都可以拿來測試!
因為他是微軟內建的工具,所以由微軟的網站上可以得到相關的使用說明,請參閱下面連結:
詳細的WinSAT使用方式
由上面的連結中,你可以發現其他的內建工具的用法,找找看,或許你會發現更好玩的東西喔!
幾個測試範例:
1. WinSAT cpu d3d -objs C(20) -texshader -totalobj 100 -time 60 -v -compression
2.WinSAT cpu aurora -time 120 -v -encryption
3.WinSAT d3d -texshader -totalobj 300 -time 120 -v
Reference
http://technet.microsoft.com
標籤:
Windows 程式相關
星期一, 7月 28, 2008
MSN Messenger 8.5 故障排除
前幾天突然MSN 都不能連線,查詢狀態後發現是MSN Server掛掉的問題,所以一堆人早上都不能上線。
本來想說反正等一會兒後就應該可以上線了,看著其他同事們一個個都連上線後我開始懷疑我的系統有問題了。ㄧ開始只是覺得可能是我的MSN是屬於xxx@msn.com 可能伺服器不同於Hotmail ,所以想多在等等看好了,直到下了班回到家使用了較舊版的MSN 後才發現這是MSN 8.5的問題...
因此,自己思考了一下我在這些時間中系統變更了哪些東西:
1.安裝了小紅傘掃毒程式
2.更新了Windows Installer 3.0
3.更新了MSN8.5
4.掃了一些廣告 & Virus
5.安裝了MSNEdit
在判斷後覺得,應該是更新MSN 8.5 的問題,因為其他的部份會有關係的地方大概就是掃毒程式防火牆的設定,但是把防火牆關閉後還是無法用MSN 8.5 登入,可是我使用MSN8.5 工具->選項->連線設定->Http測試後,MSN回報的訊息是"成功,你可以連線至MSN 服務",因此我不覺得我的網路連線有問題(ㄧ般IE/Firefox 也可以正常顯示網頁),也不覺得是MSN伺服器的問題,因為點選MSN登入畫面上的"服務狀態"的回報結果是 【所有系統皆穩定執行中。】
如此令人詭異的測試結果讓我覺得應該找個舊版的MSN試試看,因此我拿了XP內建的MSN登入,結果如同預期的是可以正常登入,所以強烈的懷疑是MSN 8.5的設定有問題。
懷疑是MSN 8.5的設定有問題那會是誰造成的? 原本我是懷疑MSNEdit造成的,但是在我安裝MSNEdit前就已經不行登入,所以我還是懷疑是更新了 MSN 8.5 後的設定與我原先的MSN相衝突。
因此,這時候就使用了無敵刪除大法,呼叫出Regedit(開始->執行,鍵入"Regedit") ,然後把下面的鍵值找出來,並且全部刪除看看:
HKEY_CURRENT_USER/Software/Microsoft/MSNMessenger
刪除後,奇妙的事情就發生了,MSN 8.5能登入了....真是令人OOXX#>X@!....
不管如何,MSN又可以正常使用了......^^
MSN 故障排除的幾個要點:
1.確認IE 的Proxy 設定,因為MSN會參考他,另外如果你的Proxy需要使用者名稱/密碼,請至MSN->工具->選項->連線->連線設定, Http 輸入
2.確認IE設定正確 : 工具->網際網路選項->進階 使用SSL2.0與SSL3.0有打勾
3.確認防火牆設定 : 區域連線->內容->進階->Windows防火牆 ->設定值->例外
程式和服務: 新增程式 ->選Windows Live Messenger
如果上述的方式不行,則可以試試看:
1.關閉Proxy
2.關閉防火牆
3.刪除Reg鍵值
4.連絡你們家的MIS
[Note] MSN 8.5 軟體需求
XP SP2 (如果你不是SP2的話可能會不能用)
WindowsInstaller 3.0 (如果你想網路更新的話)
本來想說反正等一會兒後就應該可以上線了,看著其他同事們一個個都連上線後我開始懷疑我的系統有問題了。ㄧ開始只是覺得可能是我的MSN是屬於xxx@msn.com 可能伺服器不同於Hotmail ,所以想多在等等看好了,直到下了班回到家使用了較舊版的MSN 後才發現這是MSN 8.5的問題...
因此,自己思考了一下我在這些時間中系統變更了哪些東西:
1.安裝了小紅傘掃毒程式
2.更新了Windows Installer 3.0
3.更新了MSN8.5
4.掃了一些廣告 & Virus
5.安裝了MSNEdit
在判斷後覺得,應該是更新MSN 8.5 的問題,因為其他的部份會有關係的地方大概就是掃毒程式防火牆的設定,但是把防火牆關閉後還是無法用MSN 8.5 登入,可是我使用MSN8.5 工具->選項->連線設定->Http測試後,MSN回報的訊息是"成功,你可以連線至MSN 服務",因此我不覺得我的網路連線有問題(ㄧ般IE/Firefox 也可以正常顯示網頁),也不覺得是MSN伺服器的問題,因為點選MSN登入畫面上的"服務狀態"的回報結果是 【所有系統皆穩定執行中。】
如此令人詭異的測試結果讓我覺得應該找個舊版的MSN試試看,因此我拿了XP內建的MSN登入,結果如同預期的是可以正常登入,所以強烈的懷疑是MSN 8.5的設定有問題。
懷疑是MSN 8.5的設定有問題那會是誰造成的? 原本我是懷疑MSNEdit造成的,但是在我安裝MSNEdit前就已經不行登入,所以我還是懷疑是更新了 MSN 8.5 後的設定與我原先的MSN相衝突。
因此,這時候就使用了無敵刪除大法,呼叫出Regedit(開始->執行,鍵入"Regedit") ,然後把下面的鍵值找出來,並且全部刪除看看:
HKEY_CURRENT_USER/Software/Microsoft/MSNMessenger
刪除後,奇妙的事情就發生了,MSN 8.5能登入了....真是令人OOXX#>X@!....
不管如何,MSN又可以正常使用了......^^
MSN 故障排除的幾個要點:
1.確認IE 的Proxy 設定,因為MSN會參考他,另外如果你的Proxy需要使用者名稱/密碼,請至MSN->工具->選項->連線->連線設定, Http 輸入
2.確認IE設定正確 : 工具->網際網路選項->進階 使用SSL2.0與SSL3.0有打勾
3.確認防火牆設定 : 區域連線->內容->進階->Windows防火牆 ->設定值->例外
程式和服務: 新增程式 ->選Windows Live Messenger
如果上述的方式不行,則可以試試看:
1.關閉Proxy
2.關閉防火牆
3.刪除Reg鍵值
4.連絡你們家的MIS
[Note] MSN 8.5 軟體需求
XP SP2 (如果你不是SP2的話可能會不能用)
WindowsInstaller 3.0 (如果你想網路更新的話)
標籤:
Windows 程式相關
星期四, 7月 24, 2008
INT 15h/AX=E820h 程式範例
昨天下午拿起了ACPI Spec , 把之前還沒實做的INT15h E820h 部份拿起來練習了一下。
由Google大神找到的文件中的說明中可以了解到INT15h E820h 的用途和歷史,下面就我找到的文件中截取ㄧ部份出來給各位參考,如果要看全文的可以透過連結去查看我找到的那篇文章!
Linux MemoryCapacity Detection
OS必須知道系統實體記憶體的數量,才能夠有效的使用和管理這些實體記憶體。所以在booting階段,我們必須通過某種手段來檢測和獲取實體記憶體的總量。
由於在booting階段的絕大部分時間裏,主機處於Real Mode下,而在RealMode下,我們通過正常手段能夠訪問的實體記憶體最大只能達到1M+64K(在A20Gate被打開的情況下,否則,最大只能訪問1M),所以我們無法直接通過記憶體訪問來獲取記憶體總量。因此,剩下的唯一手段就是通過BIOS中斷。
但不幸的是,通過BIOS中斷獲取記憶體容量並非在所有情況都可以完全工作。
獲取機器記憶體容量的方法一般來講有三種方法,這三種方法都是基於BIOS INT15h中斷,它們的名稱依此為88h,E801h,E820h。
其中,88h方法是在Intel80286出現的那天起就存在的,後續的PC及其兼容機為了保持向下相容,都繼續保留了這種方法。因此,這種方法在所有的IBMPC及其兼容機上都存在,所以看起來,booting只需要這種方法就可以獲取實體記憶體總量,其他兩種方法似乎沒有存在的必要。但事實上,這種方法存在一個重要的缺陷,由於這種方法是在16-bit時代就存在的,所以,它通過16-bit寄存器來保存記憶體容量作為返回值。但16-bit所能夠表示的最大值是64KB。由於這種方法的返回值是以KB為單位,所以它能夠表示的系統最大實體記憶體容量為64 MB。而對於今天的PC機來說,64MB已經是很低的記憶體配置了,大多數PC機的實際實體記憶體配置都大於64 MB。
另外,需要注意的是,由於這種方法出現於Intel80286時代,而80286的24-bit位址匯流排能夠訪問的最大位址為16MB,所以,儘管這種方法使用16-bit寄存器能夠表示的最大記憶體數量為64MB,但標準的BIOS只允許通過這種方法獲取最大16 MB的實體記憶體數量。
為了能夠獲取大於64MB的記憶體,就必須通過另外兩種方法的一種。但並非每一台PC機都實現了這兩種方法或這兩種方法之一。
當今流行的桌面作業系統在Booting階段進行記憶體檢測的方法都是採用這三種方法,比如Microsoft WindowsNT,Linux等。所以在某些不支持E820h,E801h的PC上,它們也最多只能檢測到64 MB或16MB實體記憶體(依賴於88h的最大返回值限制)。
但請不必過分擔心,對於絕大多數現代PC機來說,至少提供了這兩種方法的一種;而對於過去的PC機,又很少有超過64MB的配置。從這個意義上來說,這已經足夠了。
INT 15h, AX=E820h Query SystemAddress Map
E820h只能用在Real Mode下使用
這個中斷調用返回所有被安裝在主機上的RAM,以及被BIOS所保留的實體記憶體範圍的記憶體映象。
Reference
http://docs.huihoo.com/gnu_linux/own_os/booting-memory_check_6.htm
Acpi Spec 3.0b
底下是範例程式下載以及執行後的結果,我是用7-Zip 免費壓縮軟體壓縮的,所以請使用最新版WinRar或是7-Zip 才能解壓縮喔...
點我下載E820範例程式 <~~記得在DOS下跑喔...
BassLow BaseHigh SizeLow SizeHigh Type
------------------------------------------------------
00000000 0000 0009FC00 0000 1 AddressRangeMemory(EfiLoaderCode)
0009FC00 0000 00000400 0000 2 AddressRangeMemory(EfiLoaderData)
000E0000 0000 00020000 0000 2 AddressRangeMemory(EfiLoaderData)
00100000 0000 363E6000 0000 1 AddressRangeMemory(EfiLoaderCode)
364E6000 0000 00003000 0000 4 AddressRangeMemory(EfiBootServiceData)
364E9000 0000 01583000 0000 1 AddressRangeMemory(EfiLoaderCode)
37A6C000 0000 00053000 0000 2 AddressRangeMemory(EfiLoaderData)
37ABF000 0000 000C6000 0000 1 AddressRangeMemory(EfiLoaderCode)
37B85000 0000 0003A000 0000 4 AddressRangeMemory(EfiBootServiceData)
37BBF000 0000 00025000 0000 1 AddressRangeMemory(EfiLoaderCode)
37BE4000 0000 00013000 0000 3 AddressRangeMemory(EfiBootServiceCode)
37BF7000 0000 00009000 0000 1 AddressRangeMemory(EfiLoaderCode)
37C00000 0000 08400000 0000 2 AddressRangeMemory(EfiLoaderData)
F8000000 0000 04000000 0000 2 AddressRangeMemory(EfiLoaderData)
FEC00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FED10000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FED18000 0000 00002000 0000 2 AddressRangeMemory(EfiLoaderData)
FED1C000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FEE00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FFF00000 0000 00100000 0000 2 AddressRangeMemory(EfiLoaderData)
看的出來這台是1MB 的BIOS ROM吧 ...^^
Dump Memory map v1.0.0 by Harrison Hsieh
由Google大神找到的文件中的說明中可以了解到INT15h E820h 的用途和歷史,下面就我找到的文件中截取ㄧ部份出來給各位參考,如果要看全文的可以透過連結去查看我找到的那篇文章!
Linux MemoryCapacity Detection
OS必須知道系統實體記憶體的數量,才能夠有效的使用和管理這些實體記憶體。所以在booting階段,我們必須通過某種手段來檢測和獲取實體記憶體的總量。
由於在booting階段的絕大部分時間裏,主機處於Real Mode下,而在RealMode下,我們通過正常手段能夠訪問的實體記憶體最大只能達到1M+64K(在A20Gate被打開的情況下,否則,最大只能訪問1M),所以我們無法直接通過記憶體訪問來獲取記憶體總量。因此,剩下的唯一手段就是通過BIOS中斷。
但不幸的是,通過BIOS中斷獲取記憶體容量並非在所有情況都可以完全工作。
獲取機器記憶體容量的方法一般來講有三種方法,這三種方法都是基於BIOS INT15h中斷,它們的名稱依此為88h,E801h,E820h。
其中,88h方法是在Intel80286出現的那天起就存在的,後續的PC及其兼容機為了保持向下相容,都繼續保留了這種方法。因此,這種方法在所有的IBMPC及其兼容機上都存在,所以看起來,booting只需要這種方法就可以獲取實體記憶體總量,其他兩種方法似乎沒有存在的必要。但事實上,這種方法存在一個重要的缺陷,由於這種方法是在16-bit時代就存在的,所以,它通過16-bit寄存器來保存記憶體容量作為返回值。但16-bit所能夠表示的最大值是64KB。由於這種方法的返回值是以KB為單位,所以它能夠表示的系統最大實體記憶體容量為64 MB。而對於今天的PC機來說,64MB已經是很低的記憶體配置了,大多數PC機的實際實體記憶體配置都大於64 MB。
另外,需要注意的是,由於這種方法出現於Intel80286時代,而80286的24-bit位址匯流排能夠訪問的最大位址為16MB,所以,儘管這種方法使用16-bit寄存器能夠表示的最大記憶體數量為64MB,但標準的BIOS只允許通過這種方法獲取最大16 MB的實體記憶體數量。
為了能夠獲取大於64MB的記憶體,就必須通過另外兩種方法的一種。但並非每一台PC機都實現了這兩種方法或這兩種方法之一。
當今流行的桌面作業系統在Booting階段進行記憶體檢測的方法都是採用這三種方法,比如Microsoft WindowsNT,Linux等。所以在某些不支持E820h,E801h的PC上,它們也最多只能檢測到64 MB或16MB實體記憶體(依賴於88h的最大返回值限制)。
但請不必過分擔心,對於絕大多數現代PC機來說,至少提供了這兩種方法的一種;而對於過去的PC機,又很少有超過64MB的配置。從這個意義上來說,這已經足夠了。
INT 15h, AX=E820h Query SystemAddress Map
E820h只能用在Real Mode下使用
這個中斷調用返回所有被安裝在主機上的RAM,以及被BIOS所保留的實體記憶體範圍的記憶體映象。
Reference
http://docs.huihoo.com/gnu_linux/own_os/booting-memory_check_6.htm
Acpi Spec 3.0b
底下是範例程式下載以及執行後的結果,我是用7-Zip 免費壓縮軟體壓縮的,所以請使用最新版WinRar或是7-Zip 才能解壓縮喔...
點我下載E820範例程式 <~~記得在DOS下跑喔...
BassLow BaseHigh SizeLow SizeHigh Type
------------------------------------------------------
00000000 0000 0009FC00 0000 1 AddressRangeMemory(EfiLoaderCode)
0009FC00 0000 00000400 0000 2 AddressRangeMemory(EfiLoaderData)
000E0000 0000 00020000 0000 2 AddressRangeMemory(EfiLoaderData)
00100000 0000 363E6000 0000 1 AddressRangeMemory(EfiLoaderCode)
364E6000 0000 00003000 0000 4 AddressRangeMemory(EfiBootServiceData)
364E9000 0000 01583000 0000 1 AddressRangeMemory(EfiLoaderCode)
37A6C000 0000 00053000 0000 2 AddressRangeMemory(EfiLoaderData)
37ABF000 0000 000C6000 0000 1 AddressRangeMemory(EfiLoaderCode)
37B85000 0000 0003A000 0000 4 AddressRangeMemory(EfiBootServiceData)
37BBF000 0000 00025000 0000 1 AddressRangeMemory(EfiLoaderCode)
37BE4000 0000 00013000 0000 3 AddressRangeMemory(EfiBootServiceCode)
37BF7000 0000 00009000 0000 1 AddressRangeMemory(EfiLoaderCode)
37C00000 0000 08400000 0000 2 AddressRangeMemory(EfiLoaderData)
F8000000 0000 04000000 0000 2 AddressRangeMemory(EfiLoaderData)
FEC00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FED10000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FED18000 0000 00002000 0000 2 AddressRangeMemory(EfiLoaderData)
FED1C000 0000 00004000 0000 2 AddressRangeMemory(EfiLoaderData)
FEE00000 0000 00001000 0000 2 AddressRangeMemory(EfiLoaderData)
FFF00000 0000 00100000 0000 2 AddressRangeMemory(EfiLoaderData)
看的出來這台是1MB 的BIOS ROM吧 ...^^
Dump Memory map v1.0.0 by Harrison Hsieh
標籤:
IA32 相關基礎知識
星期二, 7月 22, 2008
CRB V.S ERB
公板,大家都這樣叫,CRB (Customer Reference Board) ,這是入行的時候一直聽到的名詞。
記得當入行的時候很多人都跟我說I晶片公司會出ㄧ個CRB 板子,然後我們也會有個CRB BIOS,剛開始的時候搞不清楚那是什麼,後來才慢慢的有些概念。
查詢了相關文獻中指出,以前晶片組廠商各家爭鳴,但是相容性卻是個最大的問題,後來就有些廠商乾脆就自己做塊板子然後把自己的晶片組放上去,順便跟客戶展示一下Performance ,這塊板子就是所謂的CRB,用來給客戶參考用的板子。
隨著時間的演變,系統廠便直接參考CRB的設計去設計出不同的系統出來,也就是我們現在在做的事情,這樣的好處是不用擔心太多相容性的問題,而且可以快速開發出機種。
有些系統廠可能直接拿CRB板子,上面可能就多加個USB 接口就是一個機種,然後就可以拿去賣了,當然也有些系統廠特別針對某些晶片功能去設計一些特別的Features,當然售價也就不同於直接拿CRB修改的機種。
ERB, Evaluation Reference Board 當某個新的晶片組在研發過程中,總是會需要有模擬的板子來測試,因此這類型的板子會在現成的Platform 基礎上,去配置出新的晶片組的線路,並且讓BIOS廠商開始Study ㄧ些相關問題(Bring up next BIOS code),由於他是模擬的環境,所以往往Bring up出來的BIOS code跟實際上新的晶片組的CRB BIOS code還是會有些差距。
實際上我並沒有參與過CRB/ERB開發過程,畢竟我是系統端的BIOS, 因此我不能確定我所述一定正確,如有誤的地方請大家不吝指正。
記得當入行的時候很多人都跟我說I晶片公司會出ㄧ個CRB 板子,然後我們也會有個CRB BIOS,剛開始的時候搞不清楚那是什麼,後來才慢慢的有些概念。
查詢了相關文獻中指出,以前晶片組廠商各家爭鳴,但是相容性卻是個最大的問題,後來就有些廠商乾脆就自己做塊板子然後把自己的晶片組放上去,順便跟客戶展示一下Performance ,這塊板子就是所謂的CRB,用來給客戶參考用的板子。
隨著時間的演變,系統廠便直接參考CRB的設計去設計出不同的系統出來,也就是我們現在在做的事情,這樣的好處是不用擔心太多相容性的問題,而且可以快速開發出機種。
有些系統廠可能直接拿CRB板子,上面可能就多加個USB 接口就是一個機種,然後就可以拿去賣了,當然也有些系統廠特別針對某些晶片功能去設計一些特別的Features,當然售價也就不同於直接拿CRB修改的機種。
ERB, Evaluation Reference Board 當某個新的晶片組在研發過程中,總是會需要有模擬的板子來測試,因此這類型的板子會在現成的Platform 基礎上,去配置出新的晶片組的線路,並且讓BIOS廠商開始Study ㄧ些相關問題(Bring up next BIOS code),由於他是模擬的環境,所以往往Bring up出來的BIOS code跟實際上新的晶片組的CRB BIOS code還是會有些差距。
實際上我並沒有參與過CRB/ERB開發過程,畢竟我是系統端的BIOS, 因此我不能確定我所述一定正確,如有誤的地方請大家不吝指正。
星期一, 7月 21, 2008
Verb Table v.s S3 resume
前幾天在英業達的網友小偉用msn問了我一個問題,有關於Verb Table 在S3回來後不正確的問題.
他人還在大陸打拼中,目前情況不明,也不知道能不能回的了台灣........在此希望他能順利解決問題,早點回家吧!
Verb Table , 一般我們在設定的時候就是拿著Data Sheet然後設定相關的設定值進去BIOS code或是偷懶點請教廠商設定值是什麼然後加入進去,而BIOS會自己透過相關介面寫入Audio device.
在bios的觀點中,我們進入S3 前我們會去存PCI Regs 以確保HDA 相關暫存器有回填正確,當 S3 Resume 後一般我們會去回填PCI Reg 但是不會去回填Verb Table , 頂多就是拿工具去看S3 resume後Verb table是否一樣(一般都一樣),所以進入S3的時候並不會把Verb Table儲存到RAM中. 以上是我原本接觸的這部分設定時候的認知........但是經過小偉一問,我才發現原來我錯了 >.<
目前查詢到的資料如下:
Windows XP 之前的作業系統 - S3 Resume 時 , BIOS 需要自己手動回填Verb Table ,因為OS不會幫你回填.
Vista - 作業系統"理論上應該會/看似"會幫你回填 ,不過我沒找到M$有相關的說明,只有在某"紅皮"的書裡面有提到(也有可能不會=.=), 因此我們BIOS端就不需要再去填 (因為我都是接觸到這種會自己填的OS , 所以讓我以為BIOS 不用再填 一次, 由此可知 bios的知識還真的不能以偏蓋全,而且多接觸不同種類的平台才能累積更多經驗 >.<)
由於我接觸的還是某大公司的晶片組 , 而情況大概就是這樣 , 在某本書上提到的資訊是屬於保密部分,所以我也不能說太清楚,請自行查閱有關這部分的說明. 至於其他家的晶片組請自行測試.
另外BIOS如果要回填Verb Table , 做法大同小異 , 就是註冊SMI Routine , 在S3 Resume的點去跑你的Routine , 然後自己在回填一次Verb Table就可以了!
至於註冊方式, 依照各家bios做法不同,所以請自行參考BIOS廠商的範例!
他人還在大陸打拼中,目前情況不明,也不知道能不能回的了台灣........在此希望他能順利解決問題,早點回家吧!
Verb Table , 一般我們在設定的時候就是拿著Data Sheet然後設定相關的設定值進去BIOS code或是偷懶點請教廠商設定值是什麼然後加入進去,而BIOS會自己透過相關介面寫入Audio device.
在bios的觀點中,我們進入S3 前我們會去存PCI Regs 以確保HDA 相關暫存器有回填正確,當 S3 Resume 後一般我們會去回填PCI Reg 但是不會去回填Verb Table , 頂多就是拿工具去看S3 resume後Verb table是否一樣(一般都一樣),所以進入S3的時候並不會把Verb Table儲存到RAM中. 以上是我原本接觸的這部分設定時候的認知........但是經過小偉一問,我才發現原來我錯了 >.<
目前查詢到的資料如下:
Windows XP 之前的作業系統 - S3 Resume 時 , BIOS 需要自己手動回填Verb Table ,因為OS不會幫你回填.
Vista - 作業系統"理論上應該會/看似"會幫你回填 ,不過我沒找到M$有相關的說明,只有在某"紅皮"的書裡面有提到(也有可能不會=.=), 因此我們BIOS端就不需要再去填 (因為我都是接觸到這種會自己填的OS , 所以讓我以為BIOS 不用再填 一次, 由此可知 bios的知識還真的不能以偏蓋全,而且多接觸不同種類的平台才能累積更多經驗 >.<)
由於我接觸的還是某大公司的晶片組 , 而情況大概就是這樣 , 在某本書上提到的資訊是屬於保密部分,所以我也不能說太清楚,請自行查閱有關這部分的說明. 至於其他家的晶片組請自行測試.
另外BIOS如果要回填Verb Table , 做法大同小異 , 就是註冊SMI Routine , 在S3 Resume的點去跑你的Routine , 然後自己在回填一次Verb Table就可以了!
至於註冊方式, 依照各家bios做法不同,所以請自行參考BIOS廠商的範例!
星期二, 7月 15, 2008
Legacy-Free Hardware and BIOS Requirements
http://www.microsoft.com/taiwan/whdc/archive/Lf.mspx
這篇文章中可以讓你看看BIOS的最小需求為何,以及文章內的相關連結可以看到更多有關於一台PC在設計上Microsoft 是如何與Intel 去制定一些規範。
參考資料
http://www.microsoft.com/
http://www.microsoft.com/taiwan/whdc/archive/pcguides.mspx
這篇文章中可以讓你看看BIOS的最小需求為何,以及文章內的相關連結可以看到更多有關於一台PC在設計上Microsoft 是如何與Intel 去制定一些規範。
參考資料
http://www.microsoft.com/
http://www.microsoft.com/taiwan/whdc/archive/pcguides.mspx
標籤:
IA32 相關基礎知識
星期四, 6月 19, 2008
NVRAM list v.s NVStore
最近接了一個新的案子,雖然還沒開始Run但是事前的準備也不能少,也因此遇到了新問題,所以在部落格留下紀錄以後好方便查詢!
在跟客戶接觸的過程中,他們要求我提供CMOS NVRAM List ,用過P公司的BIOS的人都知道, P公司會產生這個List ,而這個List其實就是對應我們在Setup Menu中的選項設定值(例如某個item內有Enable/Disable選項而選擇後的值會存放進去CMOS當中) ,有了這份List ,客戶就可以開發自己的工廠測試程式去修改CMOS內的設定值來達到他們的需求(不考慮Checksum問題時可以這樣做)。最常見的就是修改Boot Order (修改開機順序),當然這些工具還是需要BIOS端的支援啦!
而我的問題在於EFI架構中為了一些安全性的考量,已經建議這些設定值的存放地方改至NVStore,即直接寫入至BIOS ROM中的某個規劃出來的區塊,因此我沒辦法直接修改CMOS來達到修改某個item的設定值,除非你在POST的BIOS code中去讀取你自己定義的CMOS位置然後在去改變他,這部分我們學長已經是這樣子的方式來修改BootOrder!
方式一:
AP修改CMOS --> POST過程中BIOS去讀取CMOS值 -->BIOS修改至相關Variable位置
有關於NVStore部分,在不同的bios廠商中做法也是不見得會完全依照當初的建議去做,像是P公司現階段的BIOS code就比較尷尬...因為他不是完全的EFI 架構,所以有一部分還是存放在NVRAM 中 ,一部分是存放在NVStore ,所以在過度期中他還是有提供NVRAM list,只可惜這次的案子不是使用p公司的BIOS =.=!
路不通就自己通, 因此在EFI 架構下我自己寫了一個介面給AP端使用(修改cmos在由POST 開機時讀取出來修改的方式我學長已經實做成功,所以我才試試看改寫另一種方式),方式是透過SW SMI Driver來註冊一個SMI Routine ,然後在這個Routne中去得到AP端傳進來的RAM Buffer,而這塊RAM Buffer中說明了我要去修改/讀取哪一個NV Variable 以及要寫入/回傳的資料 ,因此在DOS或是Windows下就可以很方便的透過這個介面去修改設定值。
而ap端我是採用TC++ 3.0 先去配置一塊記憶體,然後把參數寫進去這塊記憶體,然後用ESI指向這塊記憶體,接著發送SW SMI ,如下面所示
type struct {
DWORD Protocol; (Byte/word/dword)
DWORD VarIndex;
DWORD VarData;
}OEM_BUFFER
STATUS OEM_SMI_Trigger(OEM_BUFFER *inputbuf,OEM_BUFFER *outputbuf)
{
AH=Select Fun (Read/Write)
AL=SW SMI function number
ESI=input buffer
EDI=output buffer
EBX = Signature '$OEM'
DX=B2h
}
方式二:
AP端將參數寫至RAM --> AP端設定好暫存器,指向存放參數的RAM --> AP端觸發SMI --> BIOS透過暫存器得到參數 --> BIOS SMM code設定相關Variable.
結論:
透過方式一的方式簡單又方便,但是缺點在於傳遞的資料量有限,且如果變數過多時會很麻煩!
透過方式二的方式複雜但是可以傳遞較大的資料量,應用也比較廣,變數過多也無所謂,因為BIOS端會把這些item都集中然後放在某個Structure中,所以只要指定好Index就可以了(以前叫做Token),其他應用可以類似寫一個燒BIOS ROM的介面,透過BIOS本身的Code去燒...目前某家EFI BIOS公司就是這樣子去開發Flash utility...
在跟客戶接觸的過程中,他們要求我提供CMOS NVRAM List ,用過P公司的BIOS的人都知道, P公司會產生這個List ,而這個List其實就是對應我們在Setup Menu中的選項設定值(例如某個item內有Enable/Disable選項而選擇後的值會存放進去CMOS當中) ,有了這份List ,客戶就可以開發自己的工廠測試程式去修改CMOS內的設定值來達到他們的需求(不考慮Checksum問題時可以這樣做)。最常見的就是修改Boot Order (修改開機順序),當然這些工具還是需要BIOS端的支援啦!
而我的問題在於EFI架構中為了一些安全性的考量,已經建議這些設定值的存放地方改至NVStore,即直接寫入至BIOS ROM中的某個規劃出來的區塊,因此我沒辦法直接修改CMOS來達到修改某個item的設定值,除非你在POST的BIOS code中去讀取你自己定義的CMOS位置然後在去改變他,這部分我們學長已經是這樣子的方式來修改BootOrder!
方式一:
AP修改CMOS --> POST過程中BIOS去讀取CMOS值 -->BIOS修改至相關Variable位置
有關於NVStore部分,在不同的bios廠商中做法也是不見得會完全依照當初的建議去做,像是P公司現階段的BIOS code就比較尷尬...因為他不是完全的EFI 架構,所以有一部分還是存放在NVRAM 中 ,一部分是存放在NVStore ,所以在過度期中他還是有提供NVRAM list,只可惜這次的案子不是使用p公司的BIOS =.=!
路不通就自己通, 因此在EFI 架構下我自己寫了一個介面給AP端使用(修改cmos在由POST 開機時讀取出來修改的方式我學長已經實做成功,所以我才試試看改寫另一種方式),方式是透過SW SMI Driver來註冊一個SMI Routine ,然後在這個Routne中去得到AP端傳進來的RAM Buffer,而這塊RAM Buffer中說明了我要去修改/讀取哪一個NV Variable 以及要寫入/回傳的資料 ,因此在DOS或是Windows下就可以很方便的透過這個介面去修改設定值。
而ap端我是採用TC++ 3.0 先去配置一塊記憶體,然後把參數寫進去這塊記憶體,然後用ESI指向這塊記憶體,接著發送SW SMI ,如下面所示
type struct {
DWORD Protocol; (Byte/word/dword)
DWORD VarIndex;
DWORD VarData;
}OEM_BUFFER
STATUS OEM_SMI_Trigger(OEM_BUFFER *inputbuf,OEM_BUFFER *outputbuf)
{
AH=Select Fun (Read/Write)
AL=SW SMI function number
ESI=input buffer
EDI=output buffer
EBX = Signature '$OEM'
DX=B2h
}
方式二:
AP端將參數寫至RAM --> AP端設定好暫存器,指向存放參數的RAM --> AP端觸發SMI --> BIOS透過暫存器得到參數 --> BIOS SMM code設定相關Variable.
結論:
透過方式一的方式簡單又方便,但是缺點在於傳遞的資料量有限,且如果變數過多時會很麻煩!
透過方式二的方式複雜但是可以傳遞較大的資料量,應用也比較廣,變數過多也無所謂,因為BIOS端會把這些item都集中然後放在某個Structure中,所以只要指定好Index就可以了(以前叫做Token),其他應用可以類似寫一個燒BIOS ROM的介面,透過BIOS本身的Code去燒...目前某家EFI BIOS公司就是這樣子去開發Flash utility...
標籤:
IA32 相關基礎知識
訂閱:
文章 (Atom)