1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
|
TITLE AHCIACC.ASM - AHCI Register/Memory Acccess Routines
;****************************************************************************
;****************************************************************************
;** **
;** (C)Copyright 1985-2014, American Megatrends, Inc. **
;** **
;** All Rights Reserved. **
;** **
;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
;** **
;** Phone (770)-246-8600 **
;** **
;****************************************************************************
;****************************************************************************
;****************************************************************************
; $Header: /Alaska/SOURCE/Modules/AHCI/INT13/CSP/AHCIACC.ASM 14 12/08/14 5:58a Anbuprakashp $
;
; $Revision: 14 $
;
; $Date: 12/08/14 5:58a $
;****************************************************************************
; Revision History
; ----------------
; $Log: /Alaska/SOURCE/Modules/AHCI/INT13/CSP/AHCIACC.ASM $
;
; 14 12/08/14 5:58a Anbuprakashp
; [TAG] EIP192297
; [Category] Improvement
; [Description] Replacing SmmGetMemoryType usage in AHCI driver with
; AmiBufferValidationLib
; [Files] AhciInt13Smm.c, AhciInt13Smm.mak, AHCIACC.ASM
;
; 13 11/24/14 11:54p Kapilporwal
; [TAG] EIP191939
; [Category] Improvement
; [Description] Issue about BIG_REAL_MODE_MMIO_ACCESS of AHCI module
; [Files] AI13.bin
; AHCIACC.ASM
; AhciInt13Dxe.c
; AhciInt13Dxe.dxs
; AhciInt13Smm.c
; AhciInt13Smm.cif
; AhciInt13Smm.dxs
; AhciInt13Smm.h
; AhciInt13Smm.mak
; AhciInt13Smm.sdl
; AInt13.c
; Aint13.cif
; AInt13.h
; AhciSmm.c
; AhciSmm.h
; AhciSmmProtocol.h
;
; 12 7/01/14 2:23a Nagadineshk
; [TAG] EIP172162
; [Category] Bug Fix
; [Severity] Important
; [Symptom] Can't install legacy windows if achiacc.obj is not first
; one of CSM_OEM16_OBJS elink
; [RootCause] Wrong offset of Newly Hooked Interrupt(CPU Exception
; Interrupt) address loaded in Interrupt vector table.
; [Solution] Stored Correct Offset value in IVT
; [Files] AHCIACC.ASM
;
; 11 6/20/14 6:54a Nimishsv
; Recheck-in
;
; 10 12/17/13 7:06a Nimishsv
; [TAG] EIP131322
; [Category] Improvement
; [Description] Improve S4 resume time with PCIE SSD
; under Win7, reported that if enable AHCIMMIOSMM_SUPPORT,
; and then S4 resume time is very long(about 50s) with win 7.
; (Add support for accessing MMIO region using BIG real mode)
; [Files] AhciMmioSmm.sdl, AHCIACC.asm
;
; 9 8/02/12 8:14a Deepthins
; [TAG] EIP93480
; [Category] Bug Fix
; [Symptom] AHCI legacy support module is corrupting the memory.
; [RootCause] AHCI legacy support module is corrupting the memory as it
; was using wrong offset for storing the base address.
; [Solution] Properly calculating offset for storing the base address.
; [Files] AINT13.EQU, AInt13.c, AInt13.h and AHCIACC.ASM
;
; 8 1/13/12 12:20a Deepthins
; [TAG] EIP78099
; [Category] Improvement
; [Description] Handle multiple AHCI controller in legacy.
; [Files] Aint13.sdl , AInt13.c , AInt13.h , AHCIACC.ASM , AHCI.EQU ,
; AINT13.bin (AHCIACC.ASM , AINT13.EQU)
;
; 7 2/10/11 10:52a Rameshr
; [TAG] EIP53704
; [Category] Improvement
; [Description] AMI headers update for Alaska Ahci Driver
; [Files] AHCIACC.ASM
; HACCESS.EQU
; AHCI.EQU
; AINT13.EQU
; AInt13Csp.c
;
; 6 6/21/10 5:34a Rameshr
; AHCI Legacy booting through MMIO reg.
; EIP 38444
;
; 5 5/28/08 9:43a Rameshraju
; Updated the AMI Address.
;
; 4 3/28/08 10:03a Olegi
;
; 3 3/27/08 5:33p Olegi
;
; 2 19/12/07 4:28p Anandakrishnanl
; Modified the relative offsets to be absolute.
;
; 1 12/07/07 11:17a Olegi
;
;****************************************************************************
;----------------------------------------------------------------------------
; INCLUDE FILES
;----------------------------------------------------------------------------
include ahci.equ
include haccess.equ
include aint13.equ
include token.equ
FLAT_MODE_INDEX equ 08h
REAL_MODE_INDEX equ 10h
;----------------------------------------------------------------------------
; EXTERNS USED
;----------------------------------------------------------------------------
.586p
OEM16_CSEG SEGMENT PARA PUBLIC 'CODE' USE16
ASSUME cs:OEM16_CSEG, ds:OEM16_CSEG
;-------------------------------------------------------------------------
PUBLIC AhciApiModuleStart
AhciApiModuleStart LABEL BYTE
jmp SHORT AhciCsm16Api
dw AhciDataStart - AhciApiModuleStart
;----------------------------------------------------------------------------
; IMPORTANT: Do not put any OEM/CHIPSET code above this, the above code and
; and data are at fixed locations.
;----------------------------------------------------------------------------
;-------------------------------------------------------------------------
; AHCI_CSM16_API_Start
;----------------------------------------------------------------------------
; This routine is implementation of the CSM16 API #7.
; Input: CX 80h - ReadRegisterDword call
; 00h - WriteRegisterDword call
; 01h - WaitForFisRecRun call
; For read/write functions:
; SS:SP+3Eh (originally ESI) HBA Base Address
; SS:SP+42h (originally EBX) Port#, Register Offset
; Bit31-16 = Port# (0-based)
; FFFF for Generic Host Control Register
; Bit15-0 = Register offset
; SS:SP+46h (originally EAX) Data to be written
; For WaitForFisRecRun function:
; No input
; Output: NC Successful
; EAX Data read
; CY Error
; Register Usage: Do not destroy any register except EAX
;
;----------------------------------------------------------------------------
;
AhciCsm16Api PROC FAR PUBLIC
; Adjust current IP so that the data offsets are valid
call $+3 ; Push curent IP
pop bx ; Get current IP in BX
shr bx, 4
mov ax, cs ; Always x000h
add ax, bx ; New CS
push ax
push newOffset-AhciApiModuleStart
retf ; Execute from new CS:IP
newOffset:
push bp
mov bp, sp
mov eax, ss:[bp+48h] ; Data to be written (ignored for Read function)
mov ebx, ss:[bp+44h] ; Port#
mov esi, ss:[bp+40h] ; HBA Base Address
cmp cx, 0
jz aca_WriteCall
cmp cx, 80h
jnz aca_WaitForFisRecRun
call ReadRegisterDword
jmp SHORT aca_Exit
aca_WaitForFisRecRun:
call WaitForFisRecRun
jmp SHORT aca_Exit
aca_WriteCall:
call WriteRegisterDword
aca_Exit:
pop bp
; Adjust sp as if we returned to csm16_func_ret
add sp, 4 ; cs:ip of F000:csm16_func_ret
; Save EAX, restore it after popad
push eax
pop ds
pop gs
;csm16_func_ret:
popad
push gs
push ds
pop eax
pop gs
pop fs
pop es
pop ds
;csm16_exit:
popf
pop ds
pop si
add sp, 2 ; Do not "pop ax", preserving return code
; Prepare for FAR return - fetch the CS and patch the segment for RETF
mov cx, WORD PTR ss:[bp+1ah]
mov WORD PTR ss:[bp+06h], cx
; Restore CX
mov cx, WORD PTR ss:[bp+18h]
mov dx, WORD PTR ss:[bp+16h] ;Restore Dx
pop bp
add sp, 4
clc
retf 18
AhciCsm16Api ENDP
;
;-------------------------------------------------------------------------
; ReadRegisterDword
;----------------------------------------------------------------------------
; This routine reads the register.
; Input: ESI HBA Base Address
; EBX Port#, Register Offset
; Bit31-16 = Port# (0-based)
; FFFF for Generic Host Control Register
; Bit15-0 = Register offset
; Output: NC Successful
; EAX Data read
; CY Error
; Register Usage: Do not destroy any register except EAX
;
;----------------------------------------------------------------------------
;
ReadRegisterDword_FAR PROC FAR PUBLIC
call ReadRegisterDword ; EAX = data read if read
ret
ReadRegisterDword_FAR ENDP
ReadRegisterDword PROC NEAR PUBLIC
push esi
call CalculateRegisterOffset ; ESI = register offset from base
push dx ; Dx has the controller number
cli
push bx ; Save bx value in stack
push ax ; Save ax value in stack
mov ax, 0
mov al, dl ; Move the controller no into al
mov bl, 8
mul bl ; Multiply it with 8 as AHCI_ACCESS\
; structure size is 8
mov bx, ax ; Move the offset into bx
pop ax ; Restore ax
IF (MKF_AHCI_INT13_SMM_SUPPORT)
push ebx
push ecx
mov ebx, dword ptr cs:[AhciDataStart - AhciApiModuleStart +4+bx] ;ebx=Data
add esi,ebx
IF (MKF_BIG_REAL_MODE_MMIO_ACCESS)
call ReadDWORD
ELSE
mov cx,1 ;Read Function
call AhciGenerateSwSMI
cmp ecx, 0 ; if ECX == 0, MMIO read is Success
jz Read_Success
stc
jmp Read_Return
Read_Success:
clc
Read_Return:
ENDIF
pop ecx
pop ebx
jmp Read_done
ENDIF
mov dx, cs:[AhciDataStart - AhciApiModuleStart +bx] ; DX = Index Port
push eax
mov eax, esi ; EAX = register address
out dx, eax ; Write Address
pop eax
mov dx, cs:[AhciDataStart - AhciApiModuleStart +2+bx] ; DX = Data Port
in eax, dx ; EAX = adat
clc ; NC, Successful
Read_done:
pop bx
pop dx
pop esi
ret
ReadRegisterDword ENDP
;
;----------------------------------------------------------------------------
; WriteRegisterDword
;----------------------------------------------------------------------------
; This routine writes the register.
; Input: ESI HBA Base Address
; EBX Port#, Register Offset
; Bit31-16 = Port# (0-based)
; FFFF for Generic Host Control Register
; Bit15-0 = Register offset
; EAX Data to be written
; Output: NC Successful
; CY Error
; Register Usage: Do not destroy any register
;
;----------------------------------------------------------------------------
;
WriteRegisterDword_FAR PROC FAR PUBLIC
call WriteRegisterDword
ret
WriteRegisterDword_FAR ENDP
WriteRegisterDword PROC NEAR PUBLIC
push esi
call CalculateRegisterOffset ; ESI = register offset from base
push dx ; Dx has the controller number
cli
push bx ; Save bx value in stack
push ax ; Save ax value in stack
mov ax, 0
mov al, dl ; Move the controller no into al
mov bl, 8
mul bl ; Multiply it with 8 as AHCI_ACCESS\
; structure size is 8
mov bx, ax ; Move the offset into bx
pop ax ; Restore ax
IF (MKF_AHCI_INT13_SMM_SUPPORT)
push ebx
push ecx
mov ebx, dword ptr cs:[AhciDataStart - AhciApiModuleStart +4+bx]
add esi,ebx
IF (MKF_BIG_REAL_MODE_MMIO_ACCESS)
call WriteDWORD
ELSE
mov ebx,eax ;Write Value
mov cx,2 ;Write Function
call AhciGenerateSwSMI
cmp ecx, 0 ; if ECX == 0, MMIO write is Success
jz Write_Success
stc
jmp Write_Return
Write_Success:
clc
Write_Return:
ENDIF
pop ecx
pop ebx
jmp Write_done
ENDIF
mov dx, cs:[AhciDataStart - AhciApiModuleStart +bx] ; DX = Index Port
push eax
mov eax, esi ; EAX = register address
out dx, eax ; Write Address
pop eax
mov dx, cs:[AhciDataStart - AhciApiModuleStart +2+bx] ; DX = Data Port
out dx, eax ; Write dword data
clc ; NC, Successful
Write_done:
pop bx
pop dx
pop esi
ret
WriteRegisterDword ENDP
;
;----------------------------------------------------------------------------
; CalculateRegisterOffset
;----------------------------------------------------------------------------
; This routine calculates the register offset from HBA Base.
; Input: EBX Port#, Register Offset within Port
; Bit31-16 = Port# (0-based)
; FFFF for Generic Host Control Register
; Bit15-0 = Register offset
; Output: ESI Register Offset from HBA Base
; Register Usage: Do not destroy any register except ESI
;
;----------------------------------------------------------------------------
;
CalculateRegisterOffset PROC NEAR PRIVATE
push cx
push ebx
mov cx, bx ; CX = register offset
shr ebx, 16 ; BX = Port# (0-based)
inc bx ; Port# valid?
jz short cro_00 ; No
dec bx ; BX = Port# (0-based)
shl bx, PORT_REGISTER_SET_SIZE_N
add bx, PORT_REGISTER_START
cro_00:
add bx, cx ; BX = Port register offset from HBA base address
movzx esi, bx ; ESI = Port register offset from HBA base address
pop ebx
pop cx
ret
CalculateRegisterOffset ENDP
;
;----------------------------------------------------------------------------
; WaitForFisRecRun
;----------------------------------------------------------------------------
; This routine executes HBA wait for FIS rec run code. If not
; implemented (just ret), AHCI INT13 code will execute the default routine.
; Implement this routine for different OEM/Chipset vendor and return 0 in AL
; to override the default routine execution.
;
; Output: AH 0 if implemented
;
;----------------------------------------------------------------------------
;
WaitForFisRecRun PROC NEAR PUBLIC
ret
WaitForFisRecRun ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: AhciGenerateSwSMI
;
; Description: Generate the Sw SMI to read the MMIO space.
; if the system is in big real mode, read/write the MMIO space without
; SwSMI
;
; Input: Cx = 1 - Read MMIO
; Cx= 2 - Write MMIO
; Eax= Value to write in MMIO for write MMIO
;
; Output: Eax- for Read MMIO
;
; Modified: Ds
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
IF (MKF_AHCI_INT13_SMM_SUPPORT)
AhciGenerateSwSMI PROC NEAR PUBLIC
call Check_Big_Real_mode
jc NotBigReadMode
push es
push 0
pop es
cmp cx,1
je ReadMmio
mov dword ptr es:[esi],eax ;Write MMIO
pop es
ret
ReadMmio:
mov eax,dword ptr es:[esi] ;Read MMIO
pop es
ret
NotBigReadMode:
mov dx,MKF_SW_SMI_IO_ADDRESS
mov al,MKF_AHCI_INT13_SMM_SWSMI_VALUE
out dx,al ;Generate Sw SMI to Read/Write MMIO
jmp $+2
ret
AhciGenerateSwSMI ENDP
;-------------------------------------------------------------------------
; ReadDWORD
;-------------------------------------------------------------------------
; This routine reads DWORD from MMIO.
; Input: ESI HBA Base Address
;
; Output: NC Successful
; EAX Data read
; CY Error
; Register Usage: Do not destroy any register except EAX
;
;-------------------------------------------------------------------------
ReadDWORD PROC NEAR PUBLIC
push ds
push 0
pop ds
push esi
; Save original values of registers in stack
push ebx
push es
push di
; Save a dword from 5000h
mov bx, 5000h
mov es, bx
mov di, 00h
mov ebx, dword ptr es:[di]
push ebx
mov byte ptr es:[di], 00h
; Switching to Big Real Mode
call Switch_Big_Real_Mode
; Reading DWORD from Hba_base_address and store in EAX
mov eax, dword ptr ds:[esi]
push eax
movzx eax, byte ptr es:[di]
and eax, 01h
jz rdw_done
; Switch back from Big Real mode
call Switch_Original_Mode
rdw_done:
pop eax
push eax
movzx eax, byte ptr es:[di]
and eax, 10b
jz org_g20
call DisblGateA20
org_g20:
pop eax
pop ebx
; Restore the original values stored in stack
mov dword ptr es:[di], ebx
pop di
pop es
pop ebx
pop esi
pop ds
clc
ret
ReadDWORD ENDP
;-------------------------------------------------------------------------
; WriteDWORD
;-------------------------------------------------------------------------
; This routine writes DWORD in MMIO space.
; Input: EAX Data to be written
;
; Output: ESI HBA Base Address
; NC Successful
; CY Error
;
; Register Usage: Do not destroy any register except EAX
;
;-------------------------------------------------------------------------
WriteDWORD PROC NEAR PUBLIC
push ds
push 0
pop ds
push esi
; Save original values of registers in stack
push ebx
push es
push di
; Save a dword from 5000h
mov bx, 5000h
mov es, bx
mov di, 00h
mov ebx, dword ptr es:[di]
push ebx
mov byte ptr es:[di], 00h
; Switching to Big Real Mode
call Switch_Big_Real_Mode
; Writing DWORD stored in EAX into Hba_base_address
mov dword ptr ds:[esi],eax
push eax
movzx eax, byte ptr es:[di]
and eax, 01h
jz wdw_done
; Switch back from Big Real mode
call Switch_Original_Mode
wdw_done:
pop eax
push eax
movzx eax, byte ptr es:[di]
and eax, 10b
jz org_g201
call DisblGateA20
org_g201:
pop eax
pop ebx
; Restore the original values stored in stack
mov dword ptr es:[di], ebx
pop di
pop es
pop ebx
pop esi
pop ds
clc
ret
WriteDWORD ENDP
;----------------------------------------------------------------------------
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: Switch_Big_Real_Mode
;
; Description: Switch to Big real Mode.
;
; Input: None
;
; Output:
;
; Modified: DS, ES
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
;----------------------------------------------------------------------------
Switch_Big_Real_Mode PROC NEAR PUBLIC
push di
call Check_Big_Real_mode
jnc InBigRealMode
mov byte ptr es:[di], 01h
InBigRealMode:
mov di, FLAT_MODE_INDEX ;Index for flat mode
call GotoProtectedMode
pop di
ret
Switch_Big_Real_Mode ENDP
;----------------------------------------------------------------------------
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: Switch_Original_Mode
;
; Description: Switch to Original Mode.
;
; Input: None
;
; Output:
;
; Modified: DS, ES
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
;----------------------------------------------------------------------------
Switch_Original_Mode PROC NEAR PUBLIC
push di
mov di, REAL_MODE_INDEX ;Real mode index
call GotoProtectedMode
pop di
ret
Switch_Original_Mode ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: GotoProtectedMode
;
; Description: This function jumps to protected mode for 4GB limit access
;
; Input: None
;
; Output: None
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
GotoProtectedMode PROC NEAR PUBLIC
push es
pusha
cli ; Disable interrupts.
; Check the GA20 status..
; Compare 256bytes at 0:0 with FFFF:10
; If match, GA20 is disabled else GA20 is enabled.
push di
push es
push ds
push 0000h
pop ds ; DS = 0000.
push 0FFFFh
pop es ; ES = FFFF.
mov cx, 100h / 4 ; Number of Dwords in 256bytes.
xor si, si
mov di, 0010h
repz cmpsd
pop ds
pop es
pop di ;Descriptor table index in di
pushf ; Save GA20 status
; ZR/NZ = disabled/enabled.
jnz short gtbrm_00 ; GA20 is already enabled.
push di
mov di, 00h
or byte ptr es:[di], 10b
pop di
call EnblGateA20 ; Enable GateA20.
gtbrm_00:
call go_big_mode ; Go to protected mode and comeback
; to real mode.
popf ; ZR/NZ = GA20 status.
stc ; Routine went to big real mode.
gtbrm_01:
popa
pop es
ret ; Return to caller.
GotoProtectedMode ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: EnblGateA20
;
; Description: This function enables GateA20
;
; Input: None
;
; Output: None
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
EnblGateA20 PROC NEAR PUBLIC
push ax
mov al,02h
out 92h, al
; Check the GA20 status..
; Compare 256bytes at 0:0 with FFFF:10
; If match, GA20 is disabled else GA20 is enabled.
push di
push es
push ds
push 0000h
pop ds ; DS = 0000.
push 0FFFFh
pop es ; ES = FFFF.
mov cx, 100h / 4 ; Number of Dwords in 256bytes.
xor si, si
mov di, 0010h
repz cmpsd
pop ds
pop es
pop di ;Descriptor table index in di
jnz eg20_end
mov al, 0DFh ; Data for output port to enable A20.
out 60h, al
mov al, 0D1h
out 64h, al
eg20_end:
pop ax
ret
EnblGateA20 ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: go_big_mode
;
; Description: This routine goes to protected mode, sets the DS, ES to the
; given selector, comes back to real mode and sets DS, ES to 0000.
;
; Input: DX - Selector.
;
; Output: Selector 00 can be used to access 4GB.
;
; Modified: EAX.
;
; Referrals: big_gdt.
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
go_big_mode PROC NEAR PRIVATE
jmp Executable_code
;<AMI_SHDR_START>
;----------------------------------------------------------------------------
; Name: big_gdt
;
; Type: BYTE Array
;
; Description: Global Descriptor Table to switch the system to/from FLAT Mode.
; Since these routines will be called from non-shadowed system
; ROM, the GDT must be on a QWORD boundary or else the bytes
; will get CORRUPTED!
;
;----------------------------------------------------------------------------
;<AMI_SHDR_END>
ALIGN 8
big_gdt LABEL WORD
db 8 dup (0) ;00 - Null descriptor
db 0FFh,0FFh,000h,000h,000h,093h,08Fh,000h ; 08h - DS descriptor for flat mode
big_gdt_end LABEL WORD
big_gdt_real LABEL WORD
db 8 dup (0) ;00 - Null descriptor
db 0FFh,0FFh,000h,000h,000h,093h,000h,000h ; 08h - DS descriptor for real mode
big_gdt_real_end LABEL WORD
GDT_DESC LABEL BYTE
dw 010h ; Length of GDT
db 00,00h ; ptr to GDT
db 05h,00h
GDT_DESC_END LABEL BYTE
Executable_code:
push ds
push es
push eax
push ebx
push ecx
push edx
push si
push di
; Changed for CSM - need to save SS, reload SS Limit to 64K selector and restore it
push bp
mov bp, ss
mov al, 8Dh ; Disable NMI
out 70h, al
;;; Copy contents from 5000:00(16 bytes) into registers
mov ax, 5000h
mov es, ax
mov si, 00h
mov eax, dword ptr es:[si]
add si, 4
mov ebx, dword ptr es:[si]
add si, 4
mov ecx, dword ptr es:[si]
add si, 4
mov edx, dword ptr es:[si]
push eax
push ebx
push ecx
push edx
;;; Copy GDT to 5000h:00h
mov ax, cs
mov ds, ax
cmp di, 08h
jne gbm_real
mov si, offset cs:big_gdt
jmp gbm_flat
gbm_real:
mov si, offset cs:big_gdt_real
gbm_flat:
mov ax, 5000h
mov es, ax
mov di, 00h
xor cx, cx
mov cx, 08h
rep movsw
lgdt fword ptr cs:GDT_DESC
mov eax, cr0
or al, 01h
mov cr0, eax ; In protected mode.
jmp gbm_00 ; Flush instruction queue - JMP (NEAR)
; to next instruction.
gbm_00:
mov ax, 08h ; Selector
mov ds, ax ; DS = selector.
mov es, ax ; ES = selector.
mov eax, cr0 ; Come back into real mode with DS,ES
and al, 0FEh
mov cr0, eax
jmp gbm_01 ; Flush instruction queue - JMP (NEAR)
; to next instruction.
gbm_01:
xor ax, ax
mov ds, ax
mov es, ax
pop edx
pop ecx
pop ebx
;;; Restore contents of 5000:00h(16 bytes) from registers
mov ax, 5000h
mov es, ax
mov si, 00h
pop eax
mov dword ptr es:[si], eax
add si, 4
mov dword ptr es:[si], ebx
add si, 4
mov dword ptr es:[si], ecx
add si, 4
mov dword ptr es:[si], edx
pop bp
pop di
pop si
pop edx
pop ecx
pop ebx
pop eax
pop es
pop ds
ret
go_big_mode ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: DisblGateA20
;
; Description: This function disables GateA20
;
; Input: None
;
; Output: None
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
DisblGateA20 PROC NEAR PUBLIC
push ax
mov al,00h
out 92h, al
; Check the GA20 status..
; Compare 256bytes at 0:0 with FFFF:10
; If match, GA20 is disabled else GA20 is enabled.
push di
push es
push ds
push 0000h
pop ds ; DS = 0000.
push 0FFFFh
pop es ; ES = FFFF.
mov cx, 100h / 4 ; Number of Dwords in 256bytes.
xor si, si
mov di, 0010h
repz cmpsd
pop ds
pop es
pop di ;Descriptor table index in di
jz dg20_end
mov al, 0DDh ; Data for output port to disables A20.
out 60h, al
mov al, 0D1h
out 64h, al
dg20_end:
pop ax
ret
DisblGateA20 ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: Get_EBDA
;
; Description: Get the EBDA Segment Address
;
; Input: None
;
; Output: DS: Ebda Segment
;
; Modified: Ds
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Get_EBDA PROC NEAR PUBLIC
push 40h
pop ds
mov ds, ds:[0Eh] ; DS - EBDA segment.
ret
get_EBDA ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: Int0DHandler
;
; Description: Exception 0D handler
;
; Input: None
;
; Output: Exception_flag Set
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Int0DHandler PROC NEAR PUBLIC
push ds
call Get_EBDA
mov byte ptr ds:[102h],1 ;Set the Flag in Ebda:102
pop ds
pop ax
add ax, 5 ; Go to Next instruction that doesn't
; cause Exception
push ax
iret
Int0DHandler ENDP
;<AMI_PHDR_START>
;----------------------------------------------------------------------------
;
; Procedure: Check_Big_Real_mode
;
; Description: This function checks wheather system is in Big real mode
;
; Input: None
;
; Output: Carry Set - Not in Big Real mode
; Carry Not Set- System is in Big Real mode
;
; Modified: None
;
;----------------------------------------------------------------------------
;<AMI_PHDR_END>
Check_Big_Real_mode PROC NEAR PUBLIC
push eax
push edi
push ebx
push es
push ds
pushf
cli
call Get_EBDA
mov byte ptr ds:[102h],0 ;EBDA:102
push 0
pop es
mov eax, dword ptr es:[0Dh*4]
push eax
push cs ; Runtime segment
push offset cs:Int0DHandler-AhciApiModuleStart
pop eax
mov dword ptr es:[0Dh*4], eax
mov edi,0100000h
mov eax,dword ptr es:[edi]
cmp byte ptr ds:[102h],1 ;Check the exception
je Real_mode
mov edi,0
mov ebx,dword ptr es:[edi]
cmp eax,ebx
je Real_mode
;Read ,Write test for above 1Mb area
mov edi,0100000h
mov ebx,dword ptr es:[edi]
mov eax,055AA55AAh
mov dword ptr es:[edi],eax
mov eax,dword ptr es:[edi]
mov dword ptr es:[edi],ebx
cmp eax,055AA55AAh
jne Real_mode
pop eax
mov dword ptr es:[0Dh*4], eax
popf
clc ;System is in Big Real Mode
jmp Exit_Ret
Real_mode:
pop eax
mov dword ptr es:[0Dh*4], eax
popf
stc ;System is in Real Mode
Exit_Ret:
pop ds
pop es
pop ebx
pop edi
pop eax
ret
Check_Big_Real_mode ENDP
ENDIF
AhciDataStart label word
AhciAccess AHCI_ACCESS (MKF_AHCI_CONTROLLER_COUNT) dup (<>)
OEM16_CSEG ENDS
END
;****************************************************************************
;****************************************************************************
;** **
;** (C)Copyright 1985-2014, American Megatrends, Inc. **
;** **
;** All Rights Reserved. **
;** **
;** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **
;** **
;** Phone (770)-246-8600 **
;** **
;****************************************************************************
;****************************************************************************
|