132f9b796d3bb05f608d87d49e691249e5f04d13ejji#------------------------------------------------------------------------------
232f9b796d3bb05f608d87d49e691249e5f04d13ejji#*
3e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun#*   Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4b1f700a8593435e2bdc8f9b3dc21bced4774c80fhhtian#*   This program and the accompanying materials
532f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   are licensed and made available under the terms and conditions of the BSD License
632f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   which accompanies this distribution.  The full text of the license may be found at
732f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   http://opensource.org/licenses/bsd-license.php
832f9b796d3bb05f608d87d49e691249e5f04d13ejji#*
932f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1032f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1132f9b796d3bb05f608d87d49e691249e5f04d13ejji#*
1232f9b796d3bb05f608d87d49e691249e5f04d13ejji#*    bs32.asm
1332f9b796d3bb05f608d87d49e691249e5f04d13ejji#*
1432f9b796d3bb05f608d87d49e691249e5f04d13ejji#*   Abstract:
1532f9b796d3bb05f608d87d49e691249e5f04d13ejji#*
1632f9b796d3bb05f608d87d49e691249e5f04d13ejji#------------------------------------------------------------------------------
1732f9b796d3bb05f608d87d49e691249e5f04d13ejji
1832f9b796d3bb05f608d87d49e691249e5f04d13ejji        #.MODEL small
1920193e01ca7f2e20c8be6b412c8cf0a5132d1c1cklu        .stack:
2020193e01ca7f2e20c8be6b412c8cf0a5132d1c1cklu        .486p:
2120193e01ca7f2e20c8be6b412c8cf0a5132d1c1cklu        .code16
2232f9b796d3bb05f608d87d49e691249e5f04d13ejji
2332f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      FAT_DIRECTORY_ENTRY_SIZE, 0x0020
2432f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      FAT_DIRECTORY_ENTRY_SHIFT, 5
2532f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      BLOCK_SIZE, 0x0200
2632f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      BLOCK_MASK, 0x01ff
2732f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      BLOCK_SHIFT, 9
2832f9b796d3bb05f608d87d49e691249e5f04d13ejji                                               # "EFILDR_____"
2932f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      LOADER_FILENAME_PART1, 0x4c494645    # "EFIL"
3032f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      LOADER_FILENAME_PART2, 0x30325244    # "DR20"
3132f9b796d3bb05f608d87d49e691249e5f04d13ejji.equ                      LOADER_FILENAME_PART3, 0x20202030    # "0___"
3232f9b796d3bb05f608d87d49e691249e5f04d13ejji
33d5172f911d21d03a3a4f50cb6ebe89854d191e4dxli        .org 0x0
34c27b9ffe86a8c1d8476154f725682ad2afa8e7d5Tian, Hot.global _start
35fd549a4db9c562587652c23884bab5a4f3631d10gikidy_start:
3632f9b796d3bb05f608d87d49e691249e5f04d13ejjiIa32Jump:
3732f9b796d3bb05f608d87d49e691249e5f04d13ejji  jmp   BootSectorEntryPoint  # JMP inst                  - 3 bytes
3832f9b796d3bb05f608d87d49e691249e5f04d13ejji  nop
3932f9b796d3bb05f608d87d49e691249e5f04d13ejji
409ffd16fb498e2f45c68f88210d8b6daf88deacb5jjiOemId:             .ascii  "INTEL   "   # OemId               - 8 bytes
4132f9b796d3bb05f608d87d49e691249e5f04d13ejji# BPB data below will be fixed by tool
4232f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorSize:        .word  0             # Sector Size         - 16 bits
4332f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorsPerCluster: .byte  0             # Sector Per Cluster  - 8 bits
4432f9b796d3bb05f608d87d49e691249e5f04d13ejjiReservedSectors:   .word  0             # Reserved Sectors    - 16 bits
4532f9b796d3bb05f608d87d49e691249e5f04d13ejjiNoFats:            .byte  0             # Number of FATs      - 8 bits
4632f9b796d3bb05f608d87d49e691249e5f04d13ejjiRootEntries:       .word  0             # Root Entries        - 16 bits
4732f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectors:           .word  0             # Number of Sectors   - 16 bits
4832f9b796d3bb05f608d87d49e691249e5f04d13ejjiMedia:             .byte  0             # Media               - 8 bits  - ignored
4932f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorsPerFat:     .word  0             # Sectors Per FAT     - 16 bits
5032f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorsPerTrack:   .word  0             # Sectors Per Track   - 16 bits - ignored
5132f9b796d3bb05f608d87d49e691249e5f04d13ejjiHeads:             .word  0             # Heads               - 16 bits - ignored
5232f9b796d3bb05f608d87d49e691249e5f04d13ejjiHiddenSectors:     .long  0             # Hidden Sectors      - 32 bits - ignored
5332f9b796d3bb05f608d87d49e691249e5f04d13ejjiLargeSectors:      .long  0             # Large Sectors       - 32 bits
5432f9b796d3bb05f608d87d49e691249e5f04d13ejji
5532f9b796d3bb05f608d87d49e691249e5f04d13ejji#******************************************************************************
5632f9b796d3bb05f608d87d49e691249e5f04d13ejji#
5732f9b796d3bb05f608d87d49e691249e5f04d13ejji#The structure for FAT32 starting at offset 36 of the boot sector. (At this point,
5832f9b796d3bb05f608d87d49e691249e5f04d13ejji#the BPB/boot sector for FAT12 and FAT16 differs from the BPB/boot sector for FAT32.)
5932f9b796d3bb05f608d87d49e691249e5f04d13ejji#
6032f9b796d3bb05f608d87d49e691249e5f04d13ejji#******************************************************************************
6132f9b796d3bb05f608d87d49e691249e5f04d13ejji
6232f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorsPerFat32:   .long  0              # Sectors Per FAT for FAT32       - 4 bytes
6332f9b796d3bb05f608d87d49e691249e5f04d13ejjiExtFlags:          .word  0              # Mirror Flag                     - 2 bytes
6432f9b796d3bb05f608d87d49e691249e5f04d13ejjiFSVersion:         .word  0              # File System Version             - 2 bytes
6532f9b796d3bb05f608d87d49e691249e5f04d13ejjiRootCluster:       .long  0              # 1st Cluster Number of Root Dir  - 4 bytes
6632f9b796d3bb05f608d87d49e691249e5f04d13ejjiFSInfo:            .word  0              # Sector Number of FSINFO         - 2 bytes
6732f9b796d3bb05f608d87d49e691249e5f04d13ejjiBkBootSector:      .word  0              # Sector Number of Bk BootSector  - 2 bytes
6832f9b796d3bb05f608d87d49e691249e5f04d13ejjiReserved:          .fill  12, 1, 0       # Reserved Field                  - 12 bytes
6932f9b796d3bb05f608d87d49e691249e5f04d13ejjiPhysicalDrive:     .byte  0              # Physical Drive Number           - 1 byte
7032f9b796d3bb05f608d87d49e691249e5f04d13ejjiReserved1:         .byte  0              # Reserved Field                  - 1 byte
7132f9b796d3bb05f608d87d49e691249e5f04d13ejjiSignature:         .byte  0              # Extended Boot Signature         - 1 byte
7232f9b796d3bb05f608d87d49e691249e5f04d13ejjiVolId:             .ascii  "    "        # Volume Serial Number            - 4 bytes
7332f9b796d3bb05f608d87d49e691249e5f04d13ejjiFatLabel:          .ascii  "           " # Volume Label                    - 11 bytes
7432f9b796d3bb05f608d87d49e691249e5f04d13ejjiFileSystemType:    .ascii  "FAT32   "    # File System Type                - 8 bytes
7532f9b796d3bb05f608d87d49e691249e5f04d13ejjiBootSectorEntryPoint:
7632f9b796d3bb05f608d87d49e691249e5f04d13ejji        #ASSUME ds:@code
7732f9b796d3bb05f608d87d49e691249e5f04d13ejji        #ASSUME ss:@code
7832f9b796d3bb05f608d87d49e691249e5f04d13ejji
7932f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
8032f9b796d3bb05f608d87d49e691249e5f04d13ejji# Start Print
8132f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
8220193e01ca7f2e20c8be6b412c8cf0a5132d1c1cklu  movw $StartString, %si
8332f9b796d3bb05f608d87d49e691249e5f04d13ejji  call PrintString
8432f9b796d3bb05f608d87d49e691249e5f04d13ejji
8532f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
8632f9b796d3bb05f608d87d49e691249e5f04d13ejji# Print over
8732f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
8832f9b796d3bb05f608d87d49e691249e5f04d13ejji
8932f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %cs, %ax      # ax = 0
9032f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %ax, %ss      # ss = 0
9132f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  $0x1000, %ax
9232f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %ax, %ds
9332f9b796d3bb05f608d87d49e691249e5f04d13ejji
9432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  $0x7c00, %sp  # sp = 0x7c00
9532f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %sp, %bp      # bp = 0x7c00
9632f9b796d3bb05f608d87d49e691249e5f04d13ejji
9732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  $8, %ah                             # ah = 8 - Get Drive Parameters Function
9832f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  %dl, PhysicalDrive(%bp)             # BBS defines that BIOS would pass the booting driver number to the loader through DL
9932f9b796d3bb05f608d87d49e691249e5f04d13ejji  int   $0x13                               # Get Drive Parameters
10032f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw  %ax, %ax                # ax = 0
10132f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  %dh, %al                # al = dh
10232f9b796d3bb05f608d87d49e691249e5f04d13ejji  incb  %al                     # MaxHead = al + 1
10332f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw %ax                     # 0000:7bfe = MaxHead
10432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  %cl, %al                # al = cl
10532f9b796d3bb05f608d87d49e691249e5f04d13ejji  andb  $0x3f, %al              # MaxSector = al & 0x3f
10632f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw %ax                     # 0000:7bfc = MaxSector
10732f9b796d3bb05f608d87d49e691249e5f04d13ejji
10832f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpw  $0xaa55, SectorSignature(%bp)         # Verify Boot Sector Signature
10932f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   BadBootSector
11032f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  RootEntries(%bp), %cx             # cx = RootEntries
11132f9b796d3bb05f608d87d49e691249e5f04d13ejji  shlw  $FAT_DIRECTORY_ENTRY_SHIFT, %cx   # cx = cx * 32 = cx * sizeof(FAT_DIRECTORY_ENTRY) = Size of Root Directory in bytes
11232f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %cx, %bx                          # bx = size of the Root Directory in bytes
11332f9b796d3bb05f608d87d49e691249e5f04d13ejji  andw  $BLOCK_MASK, %bx                  # See if it is an even number of sectors long
11432f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   BadBootSector                     # If is isn't, then the boot sector is bad.
11532f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %cx, %bx                          # bx = size of the Root Directory in bytes
11632f9b796d3bb05f608d87d49e691249e5f04d13ejji  shrw  $BLOCK_SHIFT, %bx                 # bx = size of Root Directory in sectors
11732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  NoFats(%bp), %al                  # al = NoFats
11832f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorb  %ah, %ah                          # ah = 0  ==> ax = NoFats
11932f9b796d3bb05f608d87d49e691249e5f04d13ejji  mulw  SectorsPerFat32(%bp)              # ax = NoFats * SectorsPerFat
12032f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  ReservedSectors(%bp), %ax         # ax = NoFats * SectorsPerFat + ReservedSectors = RootLBA
12132f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  %bx, %ax                          # ax = NoFats * SectorsPerFat + ReservedSectors + RootDirSectors = FirstClusterLBA
12232f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %ax, (%bp)                        # Save FirstClusterLBA for later use
12332f9b796d3bb05f608d87d49e691249e5f04d13ejji
12432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  RootCluster(%bp), %ax             # ax = StartCluster of Root Directory
12532f9b796d3bb05f608d87d49e691249e5f04d13ejji  subw  $2, %ax                           # ax = StartCluster - 2
12632f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorb  %bh, %bh
12732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb  SectorsPerCluster(%bp), %bl       # bx = SectorsPerCluster
12832f9b796d3bb05f608d87d49e691249e5f04d13ejji  mulw  %bx                               # ax = (StartCluster - 2) * SectorsPerCluster
12932f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  (%bp), %ax                        # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
13032f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw %ds
13132f9b796d3bb05f608d87d49e691249e5f04d13ejji  popw  %es
13232f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw  %di, %di                          # Store directory in es:di = 1000:0000
13332f9b796d3bb05f608d87d49e691249e5f04d13ejji  call  ReadBlocks                        # Read StartCluster of Root Directory
13432f9b796d3bb05f608d87d49e691249e5f04d13ejji
13532f9b796d3bb05f608d87d49e691249e5f04d13ejji  # dx - variable storage (initial value is 0)
13632f9b796d3bb05f608d87d49e691249e5f04d13ejji  # bx - loader (initial value is 0)
13732f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw  %dx, %dx
13832f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw  %bx, %bx
13932f9b796d3bb05f608d87d49e691249e5f04d13ejji
14032f9b796d3bb05f608d87d49e691249e5f04d13ejjiFindEFILDR:
14132f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $LOADER_FILENAME_PART1, (%di)
14232f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindVARSTORE
14332f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $LOADER_FILENAME_PART2, 4(%di)
14432f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindVARSTORE
14532f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $LOADER_FILENAME_PART3, 7(%di)
14632f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindVARSTORE
14732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  26(%di), %bx                      # bx = Start Cluster for EFILDR  <----------------------------------
14832f9b796d3bb05f608d87d49e691249e5f04d13ejji  testw %dx, %dx
14932f9b796d3bb05f608d87d49e691249e5f04d13ejji  je    FindNext                          # Efivar.bin is not loaded
15032f9b796d3bb05f608d87d49e691249e5f04d13ejji  jmp   FoundAll
15132f9b796d3bb05f608d87d49e691249e5f04d13ejji
15232f9b796d3bb05f608d87d49e691249e5f04d13ejjiFindVARSTORE:
153fd549a4db9c562587652c23884bab5a4f3631d10gikidy  ## if the file is not loader file, see if it's "EFIVAR  BIN"
15432f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $0x56494645, (%di)                # Compare to "EFIV"
15532f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindNext
15632f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $0x20205241, 4(%di)               # Compare to "AR  "
15732f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindNext
15832f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpl  $0x4e494220, 7(%di)               # Compare to " BIN"
15932f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindNext
16032f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw  %di, %dx                          # dx = Offset of Start Cluster for Efivar.bin <---------------------
16132f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  $26, %dx
16232f9b796d3bb05f608d87d49e691249e5f04d13ejji  testw %bx, %bx
16332f9b796d3bb05f608d87d49e691249e5f04d13ejji  je    FindNext                          # Efildr is not loaded
16432f9b796d3bb05f608d87d49e691249e5f04d13ejji  jmp   FoundAll
16532f9b796d3bb05f608d87d49e691249e5f04d13ejji
16632f9b796d3bb05f608d87d49e691249e5f04d13ejjiFindNext:
16732f9b796d3bb05f608d87d49e691249e5f04d13ejji  # go to next find
16832f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw  $FAT_DIRECTORY_ENTRY_SIZE, %di    # Increment di
16932f9b796d3bb05f608d87d49e691249e5f04d13ejji  subw  $FAT_DIRECTORY_ENTRY_SIZE, %cx    # Decrement cx
17032f9b796d3bb05f608d87d49e691249e5f04d13ejji  # TODO: jump to FindVarStore if ...
17132f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne   FindEFILDR
17232f9b796d3bb05f608d87d49e691249e5f04d13ejji  jmp   NotFoundAll
17332f9b796d3bb05f608d87d49e691249e5f04d13ejji
17432f9b796d3bb05f608d87d49e691249e5f04d13ejjiFoundAll:
17532f9b796d3bb05f608d87d49e691249e5f04d13ejjiFoundEFILDR:
17632f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %bx, %cx                            # cx = Start Cluster for EFILDR  <----------------------------------
17732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %cs, %ax                            # Destination = 2000:0000
17832f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw    $0x2000, %ax
17932f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %ax, %es
18032f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw    %di, %di
18132f9b796d3bb05f608d87d49e691249e5f04d13ejjiReadFirstClusterOfEFILDR:
18232f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %cx, %ax                            # ax = StartCluster
18332f9b796d3bb05f608d87d49e691249e5f04d13ejji  subw    $2, %ax                             # ax = StartCluster - 2
18432f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorb    %bh, %bh
18532f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    SectorsPerCluster(%bp), %bl         # bx = SectorsPerCluster
18632f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw   %dx
18732f9b796d3bb05f608d87d49e691249e5f04d13ejji  mulw    %bx
18832f9b796d3bb05f608d87d49e691249e5f04d13ejji  popw    %dx                                 # ax = (StartCluster - 2) * SectorsPerCluster
18932f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw    (%bp), %ax                          # ax = FirstClusterLBA + (StartCluster-2)*SectorsPerCluster
19032f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorb    %bh, %bh
19132f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    SectorsPerCluster(%bp), %bl         # bx = Number of Sectors in a cluster
19232f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw   %es
19332f9b796d3bb05f608d87d49e691249e5f04d13ejji  call    ReadBlocks
19432f9b796d3bb05f608d87d49e691249e5f04d13ejji  popw    %ax
19532f9b796d3bb05f608d87d49e691249e5f04d13ejjiJumpIntoFirstSectorOfEFILDR:
19632f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %ax, JumpSegment(%bp)
19732f9b796d3bb05f608d87d49e691249e5f04d13ejjiJumpFarInstruction:
19832f9b796d3bb05f608d87d49e691249e5f04d13ejji  .byte   0xea
19932f9b796d3bb05f608d87d49e691249e5f04d13ejjiJumpOffset:
20032f9b796d3bb05f608d87d49e691249e5f04d13ejji  .word   0x000
20132f9b796d3bb05f608d87d49e691249e5f04d13ejjiJumpSegment:
20232f9b796d3bb05f608d87d49e691249e5f04d13ejji  .word   0x2000
20332f9b796d3bb05f608d87d49e691249e5f04d13ejji
20432f9b796d3bb05f608d87d49e691249e5f04d13ejji
20532f9b796d3bb05f608d87d49e691249e5f04d13ejjiPrintString:
20632f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw $0xb800, %ax
20732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw %ax, %es
20832f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw $0x7c0, %ax
20932f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw %ax, %ds
210e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun  movw $6, %cx
21132f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw $160, %di
21232f9b796d3bb05f608d87d49e691249e5f04d13ejji  rep
21332f9b796d3bb05f608d87d49e691249e5f04d13ejji  movsw
21432f9b796d3bb05f608d87d49e691249e5f04d13ejji  ret
21532f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
21632f9b796d3bb05f608d87d49e691249e5f04d13ejji# ReadBlocks - Reads a set of blocks from a block device
21732f9b796d3bb05f608d87d49e691249e5f04d13ejji#
21832f9b796d3bb05f608d87d49e691249e5f04d13ejji# AX    = Start LBA
21932f9b796d3bb05f608d87d49e691249e5f04d13ejji# BX    = Number of Blocks to Read
22032f9b796d3bb05f608d87d49e691249e5f04d13ejji# ES:DI = Buffer to store sectors read from disk
22132f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
22232f9b796d3bb05f608d87d49e691249e5f04d13ejji
22332f9b796d3bb05f608d87d49e691249e5f04d13ejji# cx = Blocks
22432f9b796d3bb05f608d87d49e691249e5f04d13ejji# bx = NumberOfBlocks
22532f9b796d3bb05f608d87d49e691249e5f04d13ejji# si = StartLBA
22632f9b796d3bb05f608d87d49e691249e5f04d13ejji
22732f9b796d3bb05f608d87d49e691249e5f04d13ejjiReadBlocks:
22832f9b796d3bb05f608d87d49e691249e5f04d13ejji  pusha
22932f9b796d3bb05f608d87d49e691249e5f04d13ejji  addl    LBAOffsetForBootSector(%bp), %eax            # Add LBAOffsetForBootSector to Start LBA
23032f9b796d3bb05f608d87d49e691249e5f04d13ejji  addl    HiddenSectors(%bp), %eax            # Add HiddenSectors to Start LBA
23132f9b796d3bb05f608d87d49e691249e5f04d13ejji  movl    %eax, %esi                          # esi = Start LBA
23232f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %bx, %cx                            # cx = Number of blocks to read
23332f9b796d3bb05f608d87d49e691249e5f04d13ejjiReadCylinderLoop:
23432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    $0x7bfc, %bp                        # bp = 0x7bfc
23532f9b796d3bb05f608d87d49e691249e5f04d13ejji  movl    %esi, %eax                          # eax = Start LBA
23632f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorl    %edx, %edx                          # edx = 0
23732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movzwl  (%bp), %ebx                         # bx = MaxSector
23832f9b796d3bb05f608d87d49e691249e5f04d13ejji  divl    %ebx                                # ax = StartLBA / MaxSector
23932f9b796d3bb05f608d87d49e691249e5f04d13ejji  incw    %dx                                 # dx = (StartLBA % MaxSector) + 1
24032f9b796d3bb05f608d87d49e691249e5f04d13ejji  subw    %dx, %bx                            # bx = MaxSector - Sector
24132f9b796d3bb05f608d87d49e691249e5f04d13ejji  incw    %bx                                 # bx = MaxSector - Sector + 1
24232f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpw    %bx, %cx                            # Compare (Blocks) to (MaxSector - Sector + 1)
24332f9b796d3bb05f608d87d49e691249e5f04d13ejji  jg      LimitTransfer
24432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %cx, %bx                            # bx = Blocks
24532f9b796d3bb05f608d87d49e691249e5f04d13ejjiLimitTransfer:
24632f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw   %cx
24732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    %dl, %cl                            # cl = (StartLBA % MaxSector) + 1 = Sector
24832f9b796d3bb05f608d87d49e691249e5f04d13ejji  xorw    %dx, %dx                            # dx = 0
24932f9b796d3bb05f608d87d49e691249e5f04d13ejji  divw    2(%bp)                              # ax = ax / (MaxHead + 1) = Cylinder
25032f9b796d3bb05f608d87d49e691249e5f04d13ejji                                              # dx = ax % (MaxHead + 1) = Head
25132f9b796d3bb05f608d87d49e691249e5f04d13ejji
25232f9b796d3bb05f608d87d49e691249e5f04d13ejji  pushw   %bx                                 # Save number of blocks to transfer
25332f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    %dl, %dh                            # dh = Head
25432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    $0x7c00, %bp                        # bp = 0x7c00
25532f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    PhysicalDrive(%bp), %dl             # dl = Drive Number
25632f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    %al, %ch                            # ch = Cylinder
25732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    %bl, %al                            # al = Blocks
25832f9b796d3bb05f608d87d49e691249e5f04d13ejji  movb    $2, %ah                             # ah = Function 2
25932f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %di, %bx                            # es:bx = Buffer address
26032f9b796d3bb05f608d87d49e691249e5f04d13ejji  int     $0x13
26132f9b796d3bb05f608d87d49e691249e5f04d13ejji  jc      DiskError
26232f9b796d3bb05f608d87d49e691249e5f04d13ejji  popw    %bx
26332f9b796d3bb05f608d87d49e691249e5f04d13ejji  popw    %cx
26432f9b796d3bb05f608d87d49e691249e5f04d13ejji  movzwl  %bx, %ebx
26532f9b796d3bb05f608d87d49e691249e5f04d13ejji  addl    %ebx, %esi                          # StartLBA = StartLBA + NumberOfBlocks
26632f9b796d3bb05f608d87d49e691249e5f04d13ejji  subw    %bx, %cx                            # Blocks = Blocks - NumberOfBlocks
26732f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %es, %ax
26832f9b796d3bb05f608d87d49e691249e5f04d13ejji  shlw    $(BLOCK_SHIFT-4), %bx
26932f9b796d3bb05f608d87d49e691249e5f04d13ejji  addw    %bx, %ax
27032f9b796d3bb05f608d87d49e691249e5f04d13ejji  movw    %ax, %es                            # es:di = es:di + NumberOfBlocks*BLOCK_SIZE
27132f9b796d3bb05f608d87d49e691249e5f04d13ejji  cmpw    $0, %cx
27232f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne     ReadCylinderLoop
27332f9b796d3bb05f608d87d49e691249e5f04d13ejji  popa
27432f9b796d3bb05f608d87d49e691249e5f04d13ejji  ret
27532f9b796d3bb05f608d87d49e691249e5f04d13ejji
27632f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
27732f9b796d3bb05f608d87d49e691249e5f04d13ejji# ERROR Condition:
27832f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
27932f9b796d3bb05f608d87d49e691249e5f04d13ejjiNotFoundAll:
280fd549a4db9c562587652c23884bab5a4f3631d10gikidy  ## if we found EFILDR, continue
28132f9b796d3bb05f608d87d49e691249e5f04d13ejji  testw %bx, %bx
28232f9b796d3bb05f608d87d49e691249e5f04d13ejji  jne  FoundEFILDR
28332f9b796d3bb05f608d87d49e691249e5f04d13ejjiBadBootSector:
28432f9b796d3bb05f608d87d49e691249e5f04d13ejjiDiskError:
28520193e01ca7f2e20c8be6b412c8cf0a5132d1c1cklu  movw $ErrorString, %si
28632f9b796d3bb05f608d87d49e691249e5f04d13ejji  call PrintString
28732f9b796d3bb05f608d87d49e691249e5f04d13ejjiHalt:
28832f9b796d3bb05f608d87d49e691249e5f04d13ejji  jmp   Halt
28932f9b796d3bb05f608d87d49e691249e5f04d13ejji
29032f9b796d3bb05f608d87d49e691249e5f04d13ejjiStartString:
291e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun  .byte 'B', 0x0c, 'S', 0x0c, 't', 0x0c, 'a', 0x0c, 'r', 0x0c, 't', 0x0c
29232f9b796d3bb05f608d87d49e691249e5f04d13ejjiErrorString:
293e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun  .byte 'B', 0x0c, 'E', 0x0c, 'r', 0x0c, 'r', 0x0c, 'o', 0x0c, 'r', 0x0c
29432f9b796d3bb05f608d87d49e691249e5f04d13ejji
29532f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
29632f9b796d3bb05f608d87d49e691249e5f04d13ejji# LBA Offset for BootSector, need patched by tool for HD boot.
29732f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
29832f9b796d3bb05f608d87d49e691249e5f04d13ejji
299e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun  .org 0x01fa
30032f9b796d3bb05f608d87d49e691249e5f04d13ejjiLBAOffsetForBootSector:
30132f9b796d3bb05f608d87d49e691249e5f04d13ejji  .long     0x0
30232f9b796d3bb05f608d87d49e691249e5f04d13ejji
30332f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
30432f9b796d3bb05f608d87d49e691249e5f04d13ejji# Sector Signature
30532f9b796d3bb05f608d87d49e691249e5f04d13ejji# ****************************************************************************
30632f9b796d3bb05f608d87d49e691249e5f04d13ejji
307e7c4ef5ed4a1b14c7514367a5a95e1d9c9e1f090rsun  .org 0x01fe
30832f9b796d3bb05f608d87d49e691249e5f04d13ejjiSectorSignature:
30932f9b796d3bb05f608d87d49e691249e5f04d13ejji  .word     0xaa55      # Boot Sector Signature
31032f9b796d3bb05f608d87d49e691249e5f04d13ejji
31132f9b796d3bb05f608d87d49e691249e5f04d13ejji
31232f9b796d3bb05f608d87d49e691249e5f04d13ejji
313