?? scratchpad.txt
字號:
這個補丁修正了chainloader 不能啟動WinME的IO.SYS的問題。基本原理:不同于Win98以及以前的IO.SYS,WinME的IO.SYS是經過壓縮的,因此在把IO.SYS復制到內存后,要經過解壓后才能使用,其基本過程如下:1、把IO.SYS從0x800開始的數據讀入70:0。(此步同Win98)2、把70:0的數據移到常規內存的最高處。3、以塊的形式把數據解壓回70:04、把di設為解壓后數據的長度5、設置dx的值,然后轉入70:0執行。(此步同Win98)WinME 的IO.SYS的結構:0-0x7FF: 4個扇區的BOOT程序0x800: word 0x4D43 ( 'CM' ) 壓縮IO.SYS的標志。從0x802開始是壓縮塊,每塊以3個字節的屬性字段開始。字節0:0 - 塊是非壓縮塊1 - 塊是壓縮塊對于壓縮塊,從塊開始+5處是一個0x5344的字。字節1-2:長度字段len對于壓縮塊,下一個塊的開始位置是本塊位置+1+len對于非壓縮塊,下一個塊的開始位置是本塊位置+1+2+len若某一塊的長度為0,則它標志著數據塊的結束。在數據塊后緊接著的第一個段,是程序塊,它的結構為:字節0-1:標志字節 0x4D43 ( 'CM' )字節2-3: 解壓程序相對于本塊開始的位移字節4-結束:解壓程序的代碼和數據我在附件中包含了此補丁的源程序grub-winme-1129,此補丁對應于grub_for_dos-2005-11-29.zip,并且應該在grub-0.97-patch4-emulation后使用。附件中的grub.exe和grldr是編譯后的版本,它應用了補丁patch1 - patch5, 以及grub-winme-1129。我所使用的IO.SYS也包含在附件中,它來自于英文版WinME, WinVer是 4.90.3000,大家可以測試一下其它的版本。使用源文件編譯的朋友請注意一下,以上的補丁文件因為忘了使用條件編譯,因此在編譯Grub Shell時會出現變量chain_is_winme沒有找到的錯誤,修正后的補丁文件如下。-----------------------------------------------------bean: grub-winme補丁需要改進一下。你的工作非常有難度,很漂亮。我也發現是壓縮的,我本來是打算放棄它了,正如你所看到的那樣,11-29 中已經不再能夠裝入winme了。既然要支持 WINME,那就應該更完美地支持它,否則還是不支持它了好。希望解壓過程在 builtins.c 中,如下所標明的位置: }else{ /* Read the first 640K */ read_length = filemax - chainloader_skip_length; if (read_length > 0xa0000 - (chainloader_load_segment<<4) - chainloader_load_offset) read_length = 0xa0000 - (chainloader_load_segment<<4) - chainloader_load_offset; filepos = chainloader_skip_length; if (grub_read ((char *) 0x110000, read_length) != read_length) { grub_close (); kernel_type = KERNEL_TYPE_NONE; if (errnum == ERR_NONE) errnum = ERR_EXEC_FORMAT; return 1; } grub_close (); //----------------- //可以在這里進行解壓。 //目標代碼已經讀入到 0x110000,你可以解壓到 0x1B0000, //解壓失敗,此處就有機會出錯退出,也就是說,boot 命令失敗,返回到 //GRUB 環境。這比 reboot 機器強多了。 //解壓結束后,把 0x1B0000 處的結果復制到 0x110000, //接下來就不用管了,最多修改一下chainloader_load_length 和 //read_length,讓它們都等于解壓后的文件長度就行了。 //最好不要用微軟的那一段解壓程序,而要用自己的程序,用 C 語言寫。 //----------------- }這么一來,asm.S 這個文件,似乎就沒必要再改動了。你看看上述方案可行與否?如果短時間不能解決,我們可以留到以后再解決,現在先不支持WINME。----------------------------------------------------附件里包含了新版的WinME補丁,這個版本完全用C語言編寫,而且增加了解壓的部分(原來版本是使用IO.SYS里面的函數來解壓)。IO.SYS里面使用了滑動窗口的壓縮(LZ77),而位移和長度字段均使用了變長字節編碼∶位移∶00∶后接6位數據,位移范圍 0 - 0x3F110: 后接8位數據,位移范圍 0x40 - 0x13F111: 后接12位數據,位移范圍 0x140 - 0x113F01/10: 后面7位是直接的數據,數據的最高位取0/1當出現位移0x113F是,表明一個段的結束。解壓后,除了最后一個段外,其他各個段的長度都應該是512。長度∶1∶沒有后接位,長度是201∶后接1位數據,長度范圍 3-1001∶后接2位數據,長度范圍 5-80001∶后接3位數據,長度范圍 9-0x1000001: 后接4位數據,長度范圍 0x11-0x20000001∶后接5位數據,長度范圍 0x21-0x400000001: 后接6位數據,長度范圍 0x41-0x8000000001: 后接7位數據,長度范圍 0x81-0x100000000001: 后接8位數據,長度范圍 0x101-0x200000000000: 作出錯處理附件里還包含一個獨立的應用程序expios,它把關于IO.SYS的處理分離出來,可以用作測試。其使用如下∶1、expios io.sys如果沒有輸出信息,則基本的解壓檢測通過2、expios io.sys io_out.sys把解壓后的io.sys寫入io_out.sys中,如果用二進制編輯器打開io_out.sys,應該可以看到英文的字符串。解壓后的io_out.sys不能直接作為IO.SYS,不過可以使用grub來啟動。expios.exe是編譯后的Win32命令行程序,其他系統的用戶可以用gcc來編譯∶gcc -D__unix -o expios expios.cgrub-winme-c-1129是補丁的源程序,它與前一版本的grub-winme-1129不兼容,請不要同時使用。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -