Автор: apple_rom , 17 июля 2006
Похоже, проект Uniflash загнулся - полтора года без обновлений. Потому, чтобы убить сразу несколько зайцев завожу тут подобную тему, которая не только есть продолжение юнифлеша, но и разбор на его базе процесса перешивки на "атомном" уровне, которое когда-то давно предполагалось при написании статьи по перешивке.
Чтобы отличать его от проекта uniflash, но в то же время отражать прямую преемственность не напрягая фантазию назвал как runiflash.

Итак, приступим. (Скачать исходники юнифлеша можно на родном сайте или здесь.) Излагать буду в "черновом" варианте, потому исправления, дополнения и опровержения приветствуются. После все внесется в статью по перешивке биос.

Процесс перешивки с "практическо-железной" точки зрения представляет собой доступ в те области памяти, которые в "нормальном" режиме недоступны. Чтобы получить к ним доступ (здесь и далее все подразумевает то, как сделано именно в юнифлеше, даже с учетом, что это может быть не самый лучший способ и т.п.) делаются следующие вещи:

1. Переходим в линейный режим памяти. У него могут быть разные названия (Linear/UnReal/Flat), но смысл один и тот же - 32-битный доступ. (в досе, ко всей памяти).
2. "Размапливаем" северный мост (если требуется).
3. "Размапливаем" южный мост (если требуется).
4. "Размапливаем" мультик (если требуется).
5. "Размапливаем" GPIO (если требуется).
Операция "размапливания" подразумевает программирование логики на доступ к самой FlashROM. Все эти процедуры "железозависимые" и с претензиями на реальную универсальность требуют учета всех возможных вариантов использования "защиты от записи". В частности, именно поэтому "размапливание" делится на подобны градации - специфичные для северника-южника-мультика-гпио (в "стандартном" случае размапливание подразумевает лишь южник).

Далее идут процедуры уже конкретно работы с микросхемой, которые так же специфичны для различных типов-производителей флэшек.

После для возможности корректной работы при выходе нужно будет "замапить" все до этого "размапленные" пункты и вернуться в "нормальный" режим (адресации, 16 бит).

Вот коротко так выглядит работа юнифлеша для нашей темы. Главный файл, который ответственный за прошивку - PCI.pas - его и по-тихоньку начнем разбирать.
[code:1]{$R-}
unit PCI; { Unit to communicate with chipsets }
interface[/code:1]
Здесь и дальше я буду описывать имеющуюся у себя версию 1.45re.
[code:1]uses Award, AMIBIOS, AsusBIOS, Phoenix;[/code:1]
... в которой как раз и добавлены другие биосы.
[code:1]Const
PCICfIdx = $CF8;
PCICfData = $CFC;[/code:1]
Стандартные регистры работы с PCI. Здесь и дальше, повторю, приветствуются уточнения разряда "от знающих - малознающим".
[code:1]Var
NorthFunc, SouthFunc, LPCFunc: Word;
NorthPos,SouthPos,PMUPos,CurPCIROM,PCIROMBus,PCIROMDev,PCIROMFun,LPCBase: Byte;
CurrentChipset, CurrentPCICard: string;
WantToUseAMI, AMIUsed, ChipsetFound, ROMEnabled, PCIROMEnabled: Boolean;
WantToUseAsus, AsusUsed: Boolean;
AwardUsed: Boolean; {1.42re}
PhoenixUsed: Boolean;{1.43re}[/code:1]
Из названия большинства переменных можно понять их назначение. Наши главные теперь - хххFunc - процедуры размапливания для северника, южника и мультика (которые LPC).
[code:1]PCIROMs: array[1..20] of
record
MaxSize : LongInt;
VenID, DevID : Word;
Bus, Pos : Byte;
end;
BIOSID: array[1..8] of Char; {v1.34}[/code:1]
Зачем PCIROMs сейчас не скажу (д.з. :) ), а биосайди, думаю, ясно - авардовский 8-символьный идентификатор биоса.
[code:1]Procedure OPortD( Prt : Word; Val : LongInt );
Function IPortD( Prt : Word ) : LongInt;
Function GetPCIRegD( Bus, Dev, Func, Reg : Byte ) : LongInt;
Procedure SetPCIRegD( Bus, Dev, Func, Reg : Byte; Value : LongInt );
Function LocatePIIX : {byte}Boolean; {v1.22 byte->boolean}
procedure GetBIOSID;
Procedure RomEnable( Map : boolean);
procedure ShadowDisable_Aladdin; {v1.31}
procedure ShadowRestore_Aladdin; {v1.31}[/code:1]
По названию процедур также можно понять, для чего они.
[code:1]implementation
Uses Tools,Flash,Crt,DMI;[/code:1]
Исходники разделены в много файлов, чтобы логично выделить нужное. Суть каждого опишу позже.
[code:1]{ PortD[ x ] := y }
Procedure OPortD( Prt : Word; Val : LongInt ); Assembler;
Asm
DB 66H
MOV AX,WORD PTR Val
MOV DX,Prt
DB 66H
OUT DX,AX
End;[/code:1]
Вывод в порт, все просто.
[code:1]{ y := PortD[ x ] }
Function IPortD( Prt : Word ) : LongInt; Assembler;
Asm
MOV DX,Prt
DB 66H
IN AX,DX
DB 66H
MOV DX,AX
DB 66H
SHR DX,16
End;[/code:1]
Чтение из порта.

Описание дальнейших процедур опускаю и опишу позже, дабы разбираться "от общего к частностям". Потому и переходим сразу к главной процедуре:
[code:1]Begin
if Port[$CFB]<>$FF then {v1.26}
Port[$CFB]:=Port[$CFB] or $1; {Set PCI configuration mechanism #1}
[/code:1]
Хм, самому интересно. ;)
[code:1] {Locate north bridge}
For Pos_ := 0 to $FF do
If ( GetPCIRegD( $00, Pos_ shr 3, Pos_ and $07, $00 ) and $FFFF ) <> $FFFF then
If ( GetPCIRegD( $00, Pos_ shr 3,
Pos_ and $07, $08 ) shr 8 ) = $60000 then Break;
If Pos_ = $FF then {v1.22}
Begin
LocatePIIX := False;
Exit;
End
else LocatePIIX:=True;
NorthPos := Pos_;
{Get north bridge MID & DID}
NorthMan := GetPCIRegD( $00, NorthPos shr 3, NorthPos and $07, $00 );
NorthId := GetPCIRegD( $00, NorthPos shr 3, NorthPos and $07, $00 ) shr 16;
{Get north bridge rev ID}
NorthRev := GetPCIRegD( $00, NorthPos shr 3, NorthPos and $07, $08 );
[/code:1]
Ищем на PCI "координаты" северного моста и если его находим, то получаем NorthMan (North Manufacturer ID) и NorthRev (North Revision ID).
[code:1]{Locate south bridge}
For Pos_ := 0 to $FF do
If ( GetPCIRegD( $00, Pos_ shr 3, Pos_ and $07, $00 ) and $FFFF ) <> $FFFF then
If ( GetPCIRegD( $00, Pos_ shr 3,
Pos_ and $07, $08 ) shr 8 ) = $60100 then Break;
If Pos_ = $FF then {v1.22 for i430MX}
For Pos_ := 0 to $FF do
If ( GetPCIRegD( $00, Pos_ shr 3, Pos_ and $07, $00 ) and $FFFF ) <> $FFFF then
If ( GetPCIRegD( $00, Pos_ shr 3,
Pos_ and $07, $08 ) shr 8 ) = $68000 then Break;
If Pos_ = $FF then {v1.31 for old chipsets}
For Pos_ := 0 to $FF do
If ( GetPCIRegD( $00, Pos_ shr 3, Pos_ and $07, $00 ) and $FFFF ) <> $FFFF then
If ( GetPCIRegD( $00, Pos_ shr 3,
Pos_ and $07, $08 ) shr 8 ) = $00000 then Break;
SouthPos := Pos_;
{Get south bridge MID & DID}
SouthMan := GetPCIRegD( $00, SouthPos shr 3, SouthPos and $07, $00 );
SouthID := GetPCIRegD( $00, SouthPos shr 3, SouthPos and $07, $00 ) shr 16;
{Get south bridge rev ID}
SouthRev := GetPCIRegD( $00, SouthPos shr 3, SouthPos and $07, $08 );
[/code:1]
Аналогичное проделываем для южника, но с учетом особенностей для древних систем. (Кстати - интересно было бы услышать объяснение подобных особенностей).

[code:1] CurrentChipset := '';
NorthFunc := 0; {No special treatment necessary}
SouthFunc := 0; {Same}
LPCFunc := 0; {v1.27}
NorthName:='';
SouthName:='';
LPCName:='';
[/code:1]
Задаем "нулевые" значения всем главным параметрам.

Определяем имя и процедуры размапления (если она нужна) северника по его ревизии.
[code:1] {Id northbridge}
If NorthMan = $8086 {Intel} then
Begin
case NorthId of {case v1.21}
$4A3: if NorthRev>=$10 then NorthName:='i82433NX' else NorthName:='i82433LX';
$122D: NorthName:='i82437FX';
$1235: NorthName:='i82437MX';
$1237: NorthName:='i82441FX';
$1250: NorthName:='i82439HX';
$7030: NorthName:='i82437VX';
$7100: NorthName:='i82439TX';
$7180: NorthName:='i82443LX/EX';
$7190, $7192: NorthName:='i82443BX/ZX';
$71A0, $71A2: NorthName:='i82443GX';
$84C4: NorthName:='i82454KX/GX';
$7120: NorthName:='i82810';
$7122: NorthName:='i82810-DC100';
$7124: NorthName:='i82810E';
$1130: NorthName:='i82815';
$2500: NorthName:='i82820';
$3575: NorthName:='i82830M';
$1A21: NorthName:='i82840';
$1A30: NorthName:='i82845';
$2560: NorthName:='i82845G/P';
$2530: NorthName:='i82850';
$3580: NorthName:='i8285xGM';
$3340: NorthName:='i82855PM';
$2531: NorthName:='i82860';
$2570: NorthName:='i82865'; {v1.34}
$2578: NorthName:='i82875';
$255D: NorthName:='iE7205';
$2578: NorthName:='iE7210'; {v1.39}
$2588: NorthName:='iE7221'; {v1.39}
$3592: NorthName:='iE7320'; {v1.39}
$2540: NorthName:='iE7500';
$254C: NorthName:='iE7501';
$2550: NorthName:='iE7505';
$3590: NorthName:='iE7520'; {v1.39}
$359E: NorthName:='iE7525'; {v1.39}
$0500: NorthName:='iE8870'; {v1.39}
$2580: NorthName:='i829xxx'; {v1.37}
$2590: NorthName:='i829xxxM'; {v1.39}
End;
End else
[/code:1]
Для Интела. (Крайне приветствуются дополнения по ревизиям новых и уточнения по старым железкам.)
[code:1] If NorthMan = $1106 {VIA} then
Begin
case NorthId of {case v1.21}
$505: Begin {v1.37}
NorthFunc := $0100; {VIA A8/A9 scheme}
NorthName:='VT82C505';
End;
$576: Begin
NorthFunc := $0100; {VIA A8/A9 scheme}
NorthName:='VT82C576M';
End;
$585: NorthName:='VT82C585VP/VPX';
$595: NorthName:='VT82C595/AMD-640';
$597: NorthName:='VT82C597';
$598: NorthName:='VT82C598(AT)';
$685: Begin
NorthFunc := $0100; {VIA A8/A9 scheme}
NorthName:='VT82C685';
End;
$501: NorthName:='VT8501';
$691: NorthName:='VT82C691/693(A)/694X/T';
$693: NorthName:='VT82C693(A)';
$601: NorthName:='VT8601';
$605: NorthName:='VT8605';
$391: NorthName:='VT8371';
$305: NorthName:='VT8363(A)/8365';
$3099: NorthName:='VT8366(A)';
$3091: NorthName:='VT8633';
$3101: NorthName:='VT8653';
$3102: NorthName:='VT8662';
$3103: NorthName:='VT8615';
$3112: NorthName:='VT8361';
$3133: NorthName:='VT3133';
$3148: NorthName:='VT8751';
$3128: NorthName:='VT8753(A)/8754';
$3189: NorthName:='VT8377';
$3205: NorthName:='VT8378';
End;
End else
[/code:1]
У виашки за полтора года не шибко много нового. Еще раз повторю - просьба знающим добавить, чего нет из нового железа и осветить "интересные" моменты из старого, если они есть-известны.
[code:1] If NorthMan = $1022 {AMD} then {v1.20}
Begin
case NorthId of {case v1.21}
$7006: NorthName:='AMD-751';
$700E: NorthName:='AMD-761';
$700C: NorthName:='AMD-762';
$7454: NorthName:='AMD-8151'; {v1.36}
End;
End else
[/code:1]
Да, верно и АМД делала северники. :) Продвинутые смогут еще сказать, что даже для первых пеньков были амдшные чипсеты, но еще более продвинутые справедливо уточнят, что реально это были перемаркированные виашки, а потому и айдишники были виашные (поэтому и нет их в списке).
[code:1] If NorthMan = $1039 {SiS} then
Begin
SouthFunc:=$0503; {SiS reg. 45 bits 5,2}
case NorthId of
$496: Begin
NorthFunc := $0200; {SiS reg. D0 scheme}
SouthFunc := 0;
NorthName:='SiS 85C496+497';
End;
$406: Begin
SouthFunc := $0501; {SiS internal reg. 80h}
NorthName:='SiS 501/5101/5501';
End;
$5511: Begin
SouthFunc := $0502; {SiS internal reg. 50h}
NorthName:='SiS 5511';
End;
$5571: NorthName:='SiS 5571';
$5591: NorthName:='SiS 5591/5592';
$5596: Begin
NorthName:='SiS 5596';
SouthFunc := $0502; {SiS internal reg. 50h}
LPCFunc:=LPCDetect; {v1.27}
End;
$5597: NorthName:='SiS 5597/5598/5581/5120';
$0530: NorthName:='SiS 530';
$0540: Begin
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
NorthName:='SiS 540';
End;
$5600: NorthName:='SiS 600';
$0620: NorthName:='SiS 620';
$0630: Begin
NorthName:='SiS 630';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect; {v1.27}
End;
$0635: Begin
NorthName:='SiS 635';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0640: Begin
NorthName:='SiS 640';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0645: Begin
NorthName:='SiS 645';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0646: Begin
NorthName:='SiS 645DX';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0648: Begin {v1.31}
NorthName:='SiS 648';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0650: Begin
NorthName:='SiS 650';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0651: Begin {v1.31}
NorthName:='SiS 651';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0655: Begin {v1.31}
NorthName:='SiS 655';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0730: Begin
NorthName:='SiS 730';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0733: Begin {v1.31}
NorthName:='SiS 733';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0735: Begin
NorthName:='SiS 735';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0740: Begin
NorthName:='SiS 740';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0745: Begin {v1.31}
NorthName:='SiS 745';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0746: Begin {v1.31}
NorthName:='SiS 746';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0748: Begin {v1.31}
NorthName:='SiS 748';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
$0755: Begin {v1.31}
NorthName:='SiS 755';
SouthFunc := $0504; {SiS reg. 45 bits 7,6}
LPCFunc:=LPCDetect;
End;
End;
End else
[/code:1]
SiS поделить на северники и южники сложней из-за любви к одночиповым решениям. Для одночиповых решений происходит детект мультика, чтобы установить для него процедуру размапливания. (Просьба прокомментировать знающим - видимо в "раздельночиповых" решениях бОльшая часть функций мультика была встроена в сам южник).
Плюс по "логике" SiS можно запросто продолжить список нового железа, типа:
$0xxx: Begin NorthName:='SiS xxx';
[code:1] If NorthMan = $10B9 {ALi} then
Begin
case NorthId of
$1451: begin
NorthFunc := $0300; {ALi Aladdin}
NorthName:='M1451';
end;
$1489: begin
NorthFunc := $0301; {ALi FinALi}
NorthName:='M1489';
end;
$1521: NorthName:='M1521';
$1531: NorthName:='M1531(B)';
$1541: NorthName:='M1541/1542';
$1561: NorthName:='M1561'; {v1.31}
$1621: NorthName:='M1621';
$1631: NorthName:='M1631';
$1632: NorthName:='M1632M';
$1641: NorthName:='M1641';
$1647: NorthName:='M1647';
$1651: NorthName:='M1651'; {v1.31}
$1671: NorthName:='M1671'; {v1.31}
$1672: NorthName:='M1672'; {v1.31}
End;
End else[/code:1]
ALI. Тоже уже бывший производитель.
[code:1] If NorthMan = $1166 {Reliance/ServerWorks} then {v1.25}
Begin
case NorthId of
$0007: NorthName:='Reliance NB6635';
$0008: NorthName:='Reliance NB6536';
End;
End else[/code:1]
Экзотика, не приходилось шить такие. :)
[code:1] If NorthMan = $1066 {PicoPower} then {v1.25}
Begin
case NorthId of
$0001: NorthName:='Vesuvius V1-LS';
End;
End else[/code:1]
Что-то ужасно древнючее, уже и не помню, вроде, встречал в четверках. В общем - артефакт.
[code:1] If NorthMan = $1078 {Cyrix} then {v1.25}
Begin
case NorthId of
$0001: NorthName:='MediaGX';
End;
End else[/code:1]
Шил такие. В интернет-приставках.
[code:1] If NorthMan = $1045 {OPTi} then {v1.26}
Begin
case NorthId of
$C557: NorthName:='OPTi 82C557(M)'; {v1.37}
$C567: NorthName:='OPTi 82C567';
end;
End else
[/code:1]
Вы не видели Pentium-16Mhz??? (или даже 8Mhz, точно уже не помню). Счастливые обладатели подобных чипсетов запросто могли себя таким порадовать.
[code:1] If NorthMan = $3388 {HiNT} then {v1.26}
Begin
case NorthId of
$8011: NorthName:='HiNT VXPro-II North';
end;
End else
[/code:1]
По этому "уникуму" с ходу и не скажу - позже, может чего вспомню или кто подскажет сам.
[code:1] If NorthMan = $1060 {UMC} then {v1.28}
Begin
case NorthId of
$8881: NorthName:='UMC UM8881F';
end;
End else[/code:1]
То ли северники раньше были простые, как мультики, то ли мультики теперь такие сложные, как раньше северники... ;)
[code:1] If NorthMan = $1344 {Micron} then {v1.29}
Begin
case NorthId of
$3320: NorthName:='Micron MT8LLN21PADF';
end;
End else[/code:1]
Еще один артефакт.
[code:1] If NorthMan = $1080 {Contaq/Cypress} then {v1.29}
Begin
case NorthId of
$0600: begin {CY82C599}
NorthFunc := $0400;
NorthName:='CY82C599';
end;
$C691: NorthName:='CY82C691';
end;
End else[/code:1]
Были такие, точно :) . Еще, вроде, их как-то перемаркировывали.
[code:1] If NorthMan = $10DE {nVidia} then {v1.30}
Begin
case NorthId of
$1A4: NorthName:='nVidia IGP';
$1E0: NorthName:='nVidia IGP2';
$D1: NorthName:='nVidia nForce3 Host Bridge'; {v1.41re}
$E1: NorthName:='nVidia nForce3 250Gb Host Bridge'; {v1.41re}
end;
End else[/code:1]
Просьба знающих и/или просто фанатов нВидиа поделиться айдишниками вашего железа, что нет в этом списке. :)
[code:1] If NorthMan = $1002 {ATI} then {v1.46re}
Begin
case NorthId of
... тут может быть ваш чипсет ... :)
end;
End;
[/code:1]
Аналогично (подсказать ревизии мостов) по ATI, которая даже не упоминается в последней официальной версии юнифлеша. При чем не только для А64/Р4, но и для Атлонов, те, что А3-А4 были. У АТИ, вроде как, был чипсет даже для слотовых атлонов (типа А1-А2), но не уверен, что он был выпущен.
Содержимое данного поля является приватным и не предназначено для показа.

BBCode

  • HTML-теги не обрабатываются и показываются как обычный текст
  • You may use the following BBCode tags:
    • [align]
    • [b]
    • [code]
    • [color]
    • [font]
    • [hr]
    • [i]
    • [img]
    • [list]
    • [quote]
    • [s]
    • [size]
    • [spoiler]
    • [sub]
    • [sup]
    • [table]
    • [u]
    • [url]
  • Адреса веб-страниц и email-адреса преобразовываются в ссылки автоматически.

Baza

18 лет 3 месяца назад

Ставим SpeedFan, желательно последний, и берём из его директории файл pciidsdata.csv открываем вьювером типа lister ....наблюдаем внушительный список PCI устройств и DEVID

savely

18 лет 3 месяца назад

Ну, это не DEVID.

Неужели создатель Runiflasha перелопатил даташиты всех мат плат. Или это все есть в каких-то общих даташитах?

Даташиты не мат. плат, а чипсетов. Их все же поменьше. :-) Вон там списочек повыше.

Например в функции LocatePIIX есть GetPCIRegD=$68000, потом 68100

Далеко не у всех надо лезть так далеко.

DOS

17 лет 3 месяца назад

Ну шож кинем в ваши дегтю меда, ложку бочки :))
Вот апчитался вчера вашим rUniflash ом и решил его поюзать при перепрошивки одной знакомой девушки материнскую плату P2-BF т.е. у нее P3-BF и у нее по всем признакам сдох биос и я на P2-BF решил хотсвопом перешить но ваша rUniflash загружается, и сразу после определения биоса в момент когда должно появитса меню выбора действия (меню не появляется) ВИСНЕТ!! :( Я плакалЪ
Определяет при этом фсе корректно. Я еще сначала подумал мож дискета кривая, достал целочную из упоковки нулячей и попробовал опять, фсе равно.... ща вот скачал 1,40 буду пробовать
Но есть и положительный момент я пробовал давно как то просто смотреть что получится, если запустить Uni на маме P4R800-VM (Ati Radeon 9100 Intgr) старая версия не помню какая показала мне тогда Unknow но ваша новая цифиры какие-то чета типа {1002,102}+{342,4535} посмотрю точна напишу:)

DOS

17 лет 2 месяца назад

Мда... Видимо и rUniflash тоже загнулся :(
Проглядел бегло, от себя хочу сделать некоторое пояснение т.к. момент не объяснен, вдруг кому-нибудь понадобится.

Пример - процедура вывода 32-разрядного целого Val в порт Prt:
{ PortD[ x ] := y } Procedure OPortD( Prt : Word; Val : LongInt ); Assembler; Asm DB 66H MOV AX,WORD PTR Val MOV DX,Prt DB 66H OUT DX,AX End;

Касательно "db 66h" - на самом деле, 66H - машинный код т.н. префикса изменения разрядности операнда (с 16 до 32 разрядов в данном случае). Соотв., последовательность
DB 66H MOV AX,WORD PTR Val
на самом деле обозначает команду (и выполняется процессором как)
MOV EAX,DWORD PTR Val
Турбо Паскаль - 16-разрядная система, и встроенный Ассемблер просто не знает о существовании 32-разрядных команд, поэтому пришлось воспользоваться таким способом.
to apple_rom - подскажите, есть возможность включения в UniflashRE поддержки микросхемы W39V080APZ фирмы Winbond? Её ID - DAD0.

K@Gor (не проверено)

16 лет 9 месяцев назад

leonvn
Могу предложить свою доработанную версию Uniflash (я её обозначил 1.41к). Собственно и дорабатывал для включения поддержки W39V080A(PZ) в сентябре 2007
Листинг WINBOND.PAS:
Unit Winbond; { Unit to communicate with Winbond chips } Interface Implementation Uses Flash, GenFlash, Tools; Procedure WbSecErase( SAddr : LongInt );Far; {v1.29} Var Attempt, X : Byte; TimeOut : Word; Begin Attempt := 0; Repeat FlashCmd( $80 ); {Erase setup} Flash_Write($5555,$AA); Flash_Write($2AAA,$55); Flash_Write(SAddr,$50); {Erase sector containing address SAddr} TimeOut:=25000; X:=Flash_Read(SAddr); {v1.24 Toggle bit method} while ((X and $40) <> (Flash_Read(SAddr) and $40)) and (TimeOut>0) do begin X:=Flash_Read(SAddr); Wait(1000); Dec(TimeOut); end; Inc( Attempt ); FlashCmd( $F0 ); {Reset} Until ( Attempt > 3 ) or ( TimeOut>0 ); If TimeOut>0 then FlashError := 3; {erasing error} End; Procedure WbSecEraseFWH( SAddr: LongInt ); Far; {W39V040FA} {v1.29} begin {Unprotect} FOMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) and $F8); WbSecErase(SAddr); {Protect} FOMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) or $01); end; Procedure WbProtectSecProg( Pos, Data : LongInt ); Far; {W39V040FA} {v1.29} {W39V080(F)A} {v1.41k} begin {Unprotect} FOMemB(Pos and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(Pos and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) and $F8); AMDSecProg(Pos,Data); {Protect} FOMemB(Pos and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(Pos and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) or $01); end; Procedure WbProtectSecErase( SAddr: LongInt ); Far; {W39V080(F)A} {v1.41k} begin {Unprotect} FOMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) and $F8); AMDSecErase(SAddr); {Protect} FOMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10, FIMemB(SAddr and $FFFF0000+$FFC00002-LongInt(CurCInfo.Size) shl 10) or $01); end; Function WBIdChip( DevId : Byte; Var CInfo : ChipInfo ) : Boolean; Far; Begin WBIdChip := False; With CInfo do Begin {Common info for some chips v1.21} Flags := 1; {page mode} PgSize := 128; {page size} Progr := GenPageProgB; Case DevId of $C8 : Begin Name := ConstPtr( 'W29x512/5V series' ); Size := 64; End; $C1 : Begin {W29EE011, W29C010, W29C010M, W29C011A, W29EE012} Name := ConstPtr( 'W29x010/011/012/5V series' ); Size := 128; End; $45 : Begin {note: 2 write-protectable boot blocks} Name := ConstPtr( 'W29C020(C)/022/5V' ); Size := 256; End; $46 : Begin {v1.21} {note: 2 write-protectable boot blocks} Name := ConstPtr( 'W29C040/043/5V' ); PgSize := 256; {page size} Size := 512; End; $38 : Begin {v1.29} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := WbSecErase; Sectors[ 0, 0 ] := 16; {16 x 4k} Sectors[ 0, 1 ] := 32; Size := 64; Name := ConstPtr( 'W39L512/3.3V' ); End; $A1, $31 : Begin {v1.29} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := WbSecErase; Sectors[ 0, 0 ] := 32; {32 x 4k} Sectors[ 0, 1 ] := 32; Size := 128; case DevId of $A1: Name := ConstPtr( 'W39F010/5V' ); $31: Name := ConstPtr( 'W39L010/3.3V' ); end; End; $B5 : Begin {v1.29} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := WbSecErase; Sectors[ 0, 0 ] := 64; {64 x 4k} Sectors[ 0, 1 ] := 32; Size := 256; Name := ConstPtr( 'W39L020/3.3V' ); End; $B6 : Begin {v1.29} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := WbSecErase; Sectors[ 0, 0 ] := 128; {128 x 4k} Sectors[ 0, 1 ] := 32; Size := 512; Name := ConstPtr( 'W39L040/3.3V' ); End; $D6 : Begin {v1.39} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := AMDSecErase; Sectors[ 0, 0 ] := 8; {8 x 64k} Sectors[ 0, 1 ] := 512; Size := 512; Name := ConstPtr( 'W39L040A/3.3V' ); End; $3D : Begin {v1.39} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := WbSecErase; Sectors[ 0, 0 ] := 128; {128 x 4k} Sectors[ 0, 1 ] := 32; Size := 512; Name := ConstPtr( 'W39V040A/3.3V (LPC)' ); End; $34 : Begin {v1.29} Flags := 0; {sector mode} Progr := WbProtectSecProg; Erase := WbSecEraseFWH; Sectors[ 0, 0 ] := 128; {128 x 4k} Sectors[ 0, 1 ] := 32; Size := 512; Name := ConstPtr( 'W39V040FA/3.3V (Firmware Hub)' ); End; $8C : Begin {v1.29} Flags := 2; {bulk erase} Progr := AMDSecProg; Erase := AMDBulkErase; Size := 256; Name := ConstPtr( 'W49F020/5V' ); End; $0B : Begin {v1.21} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := AMDSecErase; Sectors[ 0, 0 ] := 1; {1 x 128k} Sectors[ 0, 1 ] := 1024; Sectors[ 1, 0 ] := 1; {1 x 96k} Sectors[ 1, 1 ] := 768; Sectors[ 2, 0 ] := 2; {2 x 8k} Sectors[ 2, 1 ] := 64; Sectors[ 3, 0 ] := 1; {1 x 16k} Sectors[ 3, 1 ] := 128; Size := 256; Name := ConstPtr( 'W49F002U/5V' ); End; $B0, $32 : Begin {v1.21} Flags := 0; {sector mode} Progr := AMDSecProg; Erase := AMDSecErase; Sectors[ 0, 0 ] := 3; {3 x 64k} Sectors[ 0, 1 ] := 512; Sectors[ 1, 0 ] := 1; {1 x 32k} Sectors[ 1, 1 ] := 256; Sectors[ 2, 0 ] := 2; {2 x 8k} Sectors[ 2, 1 ] := 64; Sectors[ 3, 0 ] := 1; {1 x 16k} Sectors[ 3, 1 ] := 128; Size := 256; case DevID of $B0: Name := ConstPtr( 'W49V002(A)/3.3V (LPC)' ); $32: Name := ConstPtr( 'W49V002F(A)/3.3V (Firmware Hub)' ); end; End; $D0 : Begin {v1.41k} Flags := 0; {sector mode} PgSize := 65536; Progr := WbProtectSecProg; Erase := WbProtectSecErase; Sectors[ 0, 0 ] := 16; {16 x 64k} Sectors[ 0, 1 ] := 1; Size := 1024; Name := ConstPtr( 'W39V080A/3.3V' ); End; else Exit; End; End; CInfo.Manuf := ConstPtr( 'Winbond' ); WBIdChip := True; End; Begin RegisterFlashManu( $DA, WBIdChip ); End.

Кроме того при компиляции возникли проблемы с интерфейсом проги... Короче функцию
{function _ReadKey:Char; off v1.41k} {add v1.23}
оключил. Но это про экзэшник.
Могу выслать на почту или FTP

Root

16 лет 8 месяцев назад

K@Gor
Актуально. Нужна поддержка W39V080FAP
Hi,

sorry for writing in English, but I can't speak Russian.

I looked at UniflashRE_1.47re.08_sources.zip and the Phoenix BIOS hooks look strange.
procedure Call_Platform_bin_Sub (Sub_Off : Word); assembler; asm push cs push offset @@return pop ax push cs {0F000h} push Sub_Off pop cx retf @@return: nop end;

This code will call CS:CS (instead of 0F000h:SubOff). Is that intentional?
Hm, so it jumps to F000:F000, I think it's a good idea to look what's there.