From 2621cc62fd4c10b2b60c8335242b7e02b618448f Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 10 Apr 2007 15:23:30 -0700 Subject: [PATCH] MBR: fix problems when LBA > 65535*sectors. Fix division overflow bug when LBA > 65535*sectors. Bug report by Devin Bayer. --- mbr/mbr.S | 35 +++++++++++++++++------------------ mbr/oldmbr.asm | 35 ++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/mbr/mbr.S b/mbr/mbr.S index 3eff070..1e6842b 100644 --- a/mbr/mbr.S +++ b/mbr/mbr.S @@ -29,10 +29,10 @@ .text .globl bootsec -stack = 0x7c00 -driveno = (stack-6) -heads = (stack-8) -sectors = (stack-10) +stack = 0x7c00 +driveno = (stack-6) +sectors = (stack-8) +secpercyl = (stack-10) BIOS_page = 0x462 @@ -89,12 +89,13 @@ next: /* Get (C)HS geometry */ movb $0x08, %ah int $0x13 + andw $0x3f, %cx /* Sector count */ + pushw %cx /* Save sectors on the stack */ xorw %ax, %ax movb %dh, %al /* dh = number of heads */ incw %ax /* From 0-based to count */ - pushw %ax /* Save heads on the stack */ - andw $0x3f, %cx /* Sector count */ - pushw %cx /* Save sectors on the stack */ + mulw %cx /* Heads*sectors -> sectors per cylinder */ + pushw %ax /* Save sectors/cylinder on the stack */ xorl %eax, %eax pushl %eax /* Base */ @@ -112,18 +113,16 @@ read_sector: read_sector_cbios: movl %eax, %edx shrl $16, %edx - divw (sectors) - incw %dx - movw %dx, %cx - xorw %dx, %dx - divw (heads) - /* dx = head, ax = cylinder */ + divw (secpercyl) + rorb %ah + rorb %ah + movb %ah, %cl movb %al, %ch - shrw $2, %ax - shrw %ax - andb $0xc0, %al - orb %al, %cl - movb %dl, %dh + movw %dx, %ax + divb (sectors) + movb %al, %dh + incb %ah + orb %ah, %cl movw $bootsec, %bx movw $0x0201, %ax jmp read_common diff --git a/mbr/oldmbr.asm b/mbr/oldmbr.asm index 31bf1fd..f3e6728 100644 --- a/mbr/oldmbr.asm +++ b/mbr/oldmbr.asm @@ -1,6 +1,6 @@ ; ----------------------------------------------------------------------- ; -; Copyright 2003-2004 H. Peter Anvin - All Rights Reserved +; Copyright 2003-2007 H. Peter Anvin - All Rights Reserved ; ; Permission is hereby granted, free of charge, to any person ; obtaining a copy of this software and associated documentation @@ -81,12 +81,13 @@ next: ; mov ah,08h ; Get drive parameters int 13h + and cx,3Fh ; Max sector number + mov [Sectors],cx xor ax,ax mov al,dh inc ax ; From 0-based to count - mov [Heads],ax - and cl,3Fh ; Max sector number - mov [Sectors],cl + mul cx ; Heads*Sectors + mov [SecPerCyl],ax ; Note: we actually don't care about the number of ; cylinders, since that's the highest-order division @@ -142,18 +143,18 @@ no_ebios: push di mov ax,[di+8] mov dx,[di+10] - div word [Sectors] - inc dx - mov cx,dx ; Sector # - xor dx,dx - div word [Heads] - ; DX = head #, AX = cylinder # - mov ch,al - shr ax,1 - shr ax,1 - and al,0C0h - or cl,al - mov dh,dl ; Head # + div word [SecPerCyl] ; AX = cylinder DX = sec in cyl + ror ah,1 + ror ah,1 + mov cl,ah + mov ch,al ; CL = cyl[9:8], CH = cyl[7:0] + + mov ax,dx + div byte [Sectors] ; AL = head AH = sector + mov dh,al + inc ah + or cl,ah ; CX = cylinder and sector + mov dl,[DriveNo] mov bx,7C00h mov ax,0201h ; Read one sector @@ -207,7 +208,7 @@ dapa: dd 0 ; LBA (MSW) ; CHS information -Heads: dw 0 +SecPerCyl: dw 0 ; Heads*Sectors Sectors: dw 0 ; Error messages -- 2.7.4