I just made next version of Linld: 0.94
http://port.imtp.ilyichevsk.odessa.ua/linux/vda/linld/linld094.tar.bz2
(20k)
http://port.imtp.ilyichevsk.odessa.ua/linux/vda/linld/linld_devel.tar.bz2
(500k)
Changelog
---------
0.91 Added support for cl=@filename
0.92 VCPI vodoo magic: booting under EMM386 and foes :-)
0.93 Cleanup. cl=@filename: cr/lf will be converted to two spaces
0.94 Ugly workaround for DOS int 15 fn 88 breakage
I believe this workaround really should be placed in kernel:
some day we will meet BIOS with same breakage!
It also looks much less ugly there. Example patch against 2.4.16-pre1
attached. Yes, there are some unrelated code cleanup (shorter instructions,
same effect - can't resist :-).
--
vda
--- setup.S.orig Fri Nov 9 19:58:02 2001
+++ setup.S Wed Nov 28 11:42:00 2001
@@ -328,12 +328,10 @@
jnl bail820
incb (E820NR)
- movw %di, %ax
- addw $20, %ax
- movw %ax, %di
+ addw $20, %di
again820:
- cmpl $0, %ebx # check to see if
- jne jmpe820 # %ebx is set to EOF
+ testl %ebx, %ebx # check to see if
+ jnz jmpe820 # %ebx is set to EOF
bail820:
@@ -356,28 +354,62 @@
int $0x15
jc mem88
- cmpw $0x0, %cx # Kludge to handle BIOSes
- jne e801usecxdx # which report their extended
- cmpw $0x0, %dx # memory in AX/BX rather than
- jne e801usecxdx # CX/DX. The spec I have read
+ testw %cx, %cx # Kludge to handle BIOSes
+ jnz e801usecxdx # which report their extended
+ testw %dx, %dx # memory in AX/BX rather than
+ jnz e801usecxdx # CX/DX. The spec I have read
movw %ax, %cx # seems to indicate AX/BX
movw %bx, %dx # are more reasonable anyway...
e801usecxdx:
- andl $0xffff, %edx # clear sign extend
+ movzwl %dx, %edx # clear sign extend
shll $6, %edx # and go from 64k to 1k chunks
- movl %edx, (0x1e0) # store extended memory size
- andl $0xffff, %ecx # clear sign extend
- addl %ecx, (0x1e0) # and add lower memory into
- # total size.
+ movzwl %cx, %ecx # clear sign extend
+ addl %ecx, %edx # add lower memory to
+ movl %edx, (0x1e0) # extended, store
# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or
# 64mb, depending on the bios) in ax.
mem88:
#endif
+ #stc # guard against brain damage -
+ # int 15 must clear cf to indicate success
+ clc # unbelievable: some BIOSes/DOSes can leave
+ # cf as is so I had to abandon stc trick
movb $0x88, %ah
int $0x15
+ jc mem_cmos
+ testw %ax, %ax
+ jnz mem_store
+
+# Fallback: if int15/88 fails, get same data from CMOS
+# this works around extremely stupid case I had with PC not booting
+# from DOS when I put 196 megs of RAM in it
+# (it reported 0 via int15/e801 and int15/88)
+# Also this makes unnecessary for loadlin to jump thru the hoops
+# just in order to let us know ext mem size
+# (it hooks itself on int 15/88 and does CMOS reads for us)
+mem_cmos:
+ pushf
+ cli
+ movb $0x18, %al
+ outb %al, $0x70
+ #iodelay?
+ inb $0x71, %al
+ movb %al, %ah
+ #iodelay?
+ movb $0x17, %al
+ outb %al, $0x70
+ #iodelay?
+ inb $0x71, %al
+ popf
+
+mem_store:
+ cmpw $0xffff-0x400, %ax # We want to be sure it won't roll over
+ jbe mem_store2 # 16 bit value when low 1024k gets added
+ movw $0xffff-0x400, %ax # thus max memtop is 0xffff*1k = 64m-1k
+mem_store2:
movw %ax, (2)
# Set the keyboard repeat rate to the max
Followup to: <[email protected]>
By author: Denis Vlasenko <[email protected]>
In newsgroup: linux.dev.kernel
>
> I believe this workaround really should be placed in kernel:
> some day we will meet BIOS with same breakage!
>
As I already explained to Denis in private email:
a) It's not "BIOS breakage"; it's standard behaviour for DOS'
HIMEM.SYS. LOADLIN must have dealt with it, I don't know through
what exact method.
b) If we put this in the kernel, real systems will break. This isn't
a "maybe", it's a "definitely."
-hpa
--
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt <[email protected]>
[resending]
On 16 January 2002 20:13, H. Peter Anvin wrote:
> >>>>There is a much easier way to do it: intercept int 15 e801 and return
> >>>> the values in cx/dx in ax/bx. Reading the CMOS is quite broken; it
> >>>> fails if the BIOS has reserved memory for its own uses.
> >>>
> >>>Well, it does not really matter whether we intercept fn E801 or fn 88.
> >>>The question is: where to read mem size if int 15 returns 0?
> >>>Mem scan?
> >>
> >>I told you... INT 15 AX=E801 returns memory size twice, in AX/BX and
> >>CX/DX. DOS kills the first one, not the second one.
Ok, I brought old Turbo Debugger from home...
It is not true on this box I type this message right now. 128 MB RAM.
Under DOS:
INT 15 AX=E801 returns carry set and AH=86 (have no BIOS manual here to look
up this error code), other registers unchanged.
INT 15 AH=88 returns AX=0.
INT 15 AX=E820 - not tested, but obviously not working (or else kernels would
boot fine without linld/loadlin kludge or kernel patch)
So we have "triple-0" failure extracting mem size info from INT 15.
> There is a much easier way to do it: intercept int 15 e801 and return the
> values in cx/dx in ax/bx. Reading the CMOS is quite broken; it fails if
> the BIOS has reserved memory for its own uses.
Where do you propose to get memory size in this case?
> > Agreed. I hope we will never receive a bug report about BIOS stupid
> > enough to report "triple-0" :-)
>
> Such a BIOS wouldn't boot DOS (HIMEM.SYS actually), nor Windows, so the
> likelihood of that is zero. BIOS receive very little testing, that much
> is obvious (and I've actually had BIOS vendors tell me "we don't care"
> when they get a very detailed bug report with exact steps on how to
> reproduce), but booting DOS and Windows *does* get tested.
You're right, DOS/Win won't boot.
Just imagine old lovely 486 box never tested by manufacturer to work well
with 64 MB of RAM. Joe Random Hacker plays Meg-o-Rama, but BIOS does not
understand how that can be: int 15 fn 88 does not fit in 16-bit reg?!
DOS does not boot, Joe says: well, Linux rulez, it will boot! but no...
OTOH, CMOS reading hack most probably would not work either... memscan time?
--
vda
Denis Vlasenko wrote:
>
> Ok, I brought old Turbo Debugger from home...
>
> It is not true on this box I type this message right now. 128 MB RAM.
> Under DOS:
> INT 15 AX=E801 returns carry set and AH=86 (have no BIOS manual here to look
> up this error code), other registers unchanged.
AH=86 is function not supported.
However, once again, you're running UNDER DOS. You probably should
query HIMEM.SYS for the memory size,
> INT 15 AH=88 returns AX=0.
> INT 15 AX=E820 - not tested, but obviously not working (or else kernels would
> boot fine without linld/loadlin kludge or kernel patch)
>
> So we have "triple-0" failure extracting mem size info from INT 15.
... because you're running under DOS.
>
> Just imagine old lovely 486 box never tested by manufacturer to work well
> with 64 MB of RAM. Joe Random Hacker plays Meg-o-Rama, but BIOS does not
> understand how that can be: int 15 fn 88 does not fit in 16-bit reg?!
> DOS does not boot, Joe says: well, Linux rulez, it will boot! but no...
>
> OTOH, CMOS reading hack most probably would not work either... memscan time?
>
By the time 64 MB RAM became supported, INT 15 AX=E801 was already
common. For pathological cases like you describe, it's "mem=" time.
-hpa