[ramdisk] Rename ramdisk__type to WV_S_RAMDISK_T
[people/sha0/winvblock.git] / src / winvblock / ramdisk / grub4dos.c
1 /**
2  * Copyright (C) 2009-2011, Shao Miller <shao.miller@yrdsb.edu.on.ca>.
3  *
4  * This file is part of WinVBlock, derived from WinAoE.
5  *
6  * WinVBlock is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * WinVBlock is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with WinVBlock.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * @file
22  *
23  * GRUB4DOS RAM disk specifics.
24  */
25
26 #include <stdio.h>
27 #include <ntddk.h>
28
29 #include "winvblock.h"
30 #include "wv_string.h"
31 #include "portable.h"
32 #include "driver.h"
33 #include "bus.h"
34 #include "device.h"
35 #include "disk.h"
36 #include "ramdisk.h"
37 #include "debug.h"
38 #include "probe.h"
39 #include "grub4dos.h"
40
41 void
42 ramdisk_grub4dos__find (
43   void
44  )
45 {
46   PHYSICAL_ADDRESS PhysicalAddress;
47   winvblock__uint8_ptr PhysicalMemory;
48   WV_SP_PROBE_INT_VECTOR InterruptVector;
49   winvblock__uint32 Int13Hook;
50   WV_SP_PROBE_SAFE_MBR_HOOK SafeMbrHookPtr;
51   WV_SP_GRUB4DOS_DRIVE_MAPPING Grub4DosDriveMapSlotPtr;
52   winvblock__uint32 i = 8;
53   winvblock__bool FoundGrub4DosMapping = FALSE;
54   WV_SP_RAMDISK_T ramdisk_ptr;
55
56   /*
57    * Find a GRUB4DOS memory-mapped disk.  Start by looking at the
58    * real-mode IDT and following the "SafeMBRHook" INT 0x13 hook
59    */
60   PhysicalAddress.QuadPart = 0LL;
61   PhysicalMemory = MmMapIoSpace ( PhysicalAddress, 0x100000, MmNonCached );
62   if ( !PhysicalMemory )
63     {
64       DBG ( "Could not map low memory\n" );
65       return;
66     }
67   InterruptVector =
68     (WV_SP_PROBE_INT_VECTOR) (PhysicalMemory + 0x13 * sizeof *InterruptVector);
69   /* Walk the "safe hook" chain of INT 13h hooks as far as possible. */
70   while (SafeMbrHookPtr = WvProbeGetSafeHook(PhysicalMemory, InterruptVector)) {
71       if (!wv_memcmpeq(
72           SafeMbrHookPtr->VendorId,
73           "GRUB4DOS",
74           sizeof "GRUB4DOS" - 1
75         )) {
76           DBG ( "Non-GRUB4DOS INT 0x13 Safe Hook\n" );
77           InterruptVector = &SafeMbrHookPtr->PrevHook;
78           continue;
79         }
80       Grub4DosDriveMapSlotPtr = (WV_SP_GRUB4DOS_DRIVE_MAPPING) (
81           PhysicalMemory +
82           (((winvblock__uint32) InterruptVector->Segment) << 4) +
83           0x20
84         );
85       while ( i-- )
86         {
87           DBG ( "GRUB4DOS SourceDrive: 0x%02x\n",
88                 Grub4DosDriveMapSlotPtr[i].SourceDrive );
89           DBG ( "GRUB4DOS DestDrive: 0x%02x\n",
90                 Grub4DosDriveMapSlotPtr[i].DestDrive );
91           DBG ( "GRUB4DOS MaxHead: %d\n", Grub4DosDriveMapSlotPtr[i].MaxHead );
92           DBG ( "GRUB4DOS MaxSector: %d\n",
93                 Grub4DosDriveMapSlotPtr[i].MaxSector );
94           DBG ( "GRUB4DOS DestMaxCylinder: %d\n",
95                 Grub4DosDriveMapSlotPtr[i].DestMaxCylinder );
96           DBG ( "GRUB4DOS DestMaxHead: %d\n",
97                 Grub4DosDriveMapSlotPtr[i].DestMaxHead );
98           DBG ( "GRUB4DOS DestMaxSector: %d\n",
99                 Grub4DosDriveMapSlotPtr[i].DestMaxSector );
100           DBG ( "GRUB4DOS SectorStart: 0x%08x\n",
101                 Grub4DosDriveMapSlotPtr[i].SectorStart );
102           DBG ( "GRUB4DOS SectorCount: %d\n",
103                 Grub4DosDriveMapSlotPtr[i].SectorCount );
104           if ( !( Grub4DosDriveMapSlotPtr[i].DestDrive == 0xff ) )
105             {
106               DBG ( "Skipping non-RAM disk GRUB4DOS mapping\n" );
107               continue;
108             }
109           ramdisk_ptr = ramdisk__create (  );
110           if ( ramdisk_ptr == NULL )
111             {
112               DBG ( "Could not create GRUB4DOS disk!\n" );
113               return;
114             }
115           /*
116            * Possible precision loss
117            */
118           if ( Grub4DosDriveMapSlotPtr[i].SourceODD )
119             {
120               ramdisk_ptr->disk->Media = WvDiskMediaTypeOptical;
121               ramdisk_ptr->disk->SectorSize = 2048;
122             }
123           else
124             {
125               ramdisk_ptr->disk->Media =
126                 Grub4DosDriveMapSlotPtr[i].SourceDrive & 0x80 ?
127                 WvDiskMediaTypeHard : WvDiskMediaTypeFloppy;
128               ramdisk_ptr->disk->SectorSize = 512;
129             }
130           DBG ( "RAM Drive is type: %d\n", ramdisk_ptr->disk->Media );
131           ramdisk_ptr->DiskBuf =
132             ( winvblock__uint32 ) ( Grub4DosDriveMapSlotPtr[i].SectorStart *
133                                     512 );
134           ramdisk_ptr->disk->LBADiskSize = ramdisk_ptr->DiskSize =
135             ( winvblock__uint32 ) Grub4DosDriveMapSlotPtr[i].SectorCount;
136           ramdisk_ptr->disk->Heads = Grub4DosDriveMapSlotPtr[i].MaxHead + 1;
137           ramdisk_ptr->disk->Sectors =
138             Grub4DosDriveMapSlotPtr[i].DestMaxSector;
139           ramdisk_ptr->disk->Cylinders =
140             ramdisk_ptr->disk->LBADiskSize / ( ramdisk_ptr->disk->Heads *
141                                                ramdisk_ptr->disk->Sectors );
142           ramdisk_ptr->disk->Dev->Boot = TRUE;
143           FoundGrub4DosMapping = TRUE;
144           /* Add the ramdisk to the bus. */
145           if (!WvDriverBusAddDev(ramdisk_ptr->disk->Dev))
146       WvDevFree(ramdisk_ptr->disk->Dev);
147         }
148       InterruptVector = &SafeMbrHookPtr->PrevHook;
149     }
150
151   MmUnmapIoSpace ( PhysicalMemory, 0x100000 );
152   if ( !FoundGrub4DosMapping )
153     {
154       DBG ( "No GRUB4DOS drive mappings found\n" );
155     }
156 }