]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - wimboot/wimboot-2.7.3/src/int13.c
1.1.07 release
[Ventoy.git] / wimboot / wimboot-2.7.3 / src / int13.c
1 /*
2 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 */
19
20 /**
21 * @file
22 *
23 * INT 13 emulation
24 *
25 */
26
27 #include <string.h>
28 #include <stdio.h>
29 #include "wimboot.h"
30 #include "int13.h"
31 #include "vdisk.h"
32
33 /** Emulated drive number */
34 static int vdisk_drive;
35
36 /**
37 * Initialise emulation
38 *
39 * @ret drive Emulated drive number
40 */
41 int initialise_int13 ( void ) {
42
43 /* Determine drive number */
44 vdisk_drive = ( 0x80 | INT13_DRIVE_COUNT++ );
45 DBG ( "Emulating drive %#02x\n", vdisk_drive );
46
47 return vdisk_drive;
48 }
49
50 /**
51 * INT 13, 08 - Get drive parameters
52 *
53 * @ret ch Low bits of maximum cylinder number
54 * @ret cl (bits 7:6) High bits of maximum cylinder number
55 * @ret cl (bits 5:0) Maximum sector number
56 * @ret dh Maximum head number
57 * @ret dl Number of drives
58 * @ret ah Status code
59 */
60 static void int13_get_parameters ( struct bootapp_callback_params *params ) {
61 unsigned int max_cylinder = ( VDISK_CYLINDERS - 1 );
62 unsigned int max_head = ( VDISK_HEADS - 1 );
63 unsigned int max_sector = ( VDISK_SECTORS_PER_TRACK - 0 /* sic */ );
64 unsigned int num_drives;
65 unsigned int min_num_drives;
66
67 /* Calculate number of drives to report */
68 num_drives = INT13_DRIVE_COUNT;
69 min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
70 if ( num_drives < min_num_drives )
71 num_drives = min_num_drives;
72
73 /* Fill in drive parameters */
74 params->ch = ( max_cylinder & 0xff );
75 params->cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
76 params->dh = max_head;
77 params->dl = num_drives;
78 DBG2 ( "Get parameters: C/H/S = %d/%d/%d, drives = %d\n",
79 ( max_cylinder + 1 ), ( max_head + 1 ), max_sector, num_drives );
80
81 /* Success */
82 params->ah = 0;
83 }
84
85 /**
86 * INT 13, 15 - Get disk type
87 *
88 * @ret cx:dx Sector count
89 * @ret ah Type code
90 */
91 static void int13_get_disk_type ( struct bootapp_callback_params *params ) {
92 uint32_t sector_count = VDISK_COUNT;
93 uint8_t drive_type = INT13_DISK_TYPE_HDD;
94
95 /* Fill in disk type */
96 params->cx = ( sector_count >> 16 );
97 params->dx = ( sector_count & 0xffff );
98 params->ah = drive_type;
99 DBG2 ( "Get disk type: sectors = %#08x, type = %d\n",
100 sector_count, drive_type );
101 }
102
103 /**
104 * INT 13, 41 - Extensions installation check
105 *
106 * @v bx 0x55aa
107 * @ret bx 0xaa55
108 * @ret cx Extensions API support bitmap
109 * @ret ah API version
110 */
111 static void int13_extension_check ( struct bootapp_callback_params *params ) {
112
113 /* Fill in extension information */
114 params->bx = 0xaa55;
115 params->cx = INT13_EXTENSION_LINEAR;
116 params->ah = INT13_EXTENSION_VER_1_X;
117 DBG2 ( "Extensions installation check\n" );
118 }
119
120 /**
121 * INT 13, 48 - Get extended parameters
122 *
123 * @v ds:si Drive parameter table
124 * @ret ah Status code
125 */
126 static void
127 int13_get_extended_parameters ( struct bootapp_callback_params *params ) {
128 struct int13_disk_parameters *disk_params;
129
130 /* Fill in extended parameters */
131 disk_params = REAL_PTR ( params->ds, params->si );
132 memset ( disk_params, 0, sizeof ( *disk_params ) );
133 disk_params->bufsize = sizeof ( *disk_params );
134 disk_params->flags = INT13_FL_DMA_TRANSPARENT;
135 disk_params->cylinders = VDISK_CYLINDERS;
136 disk_params->heads = VDISK_HEADS;
137 disk_params->sectors_per_track = VDISK_SECTORS_PER_TRACK;
138 disk_params->sectors = VDISK_COUNT;
139 disk_params->sector_size = VDISK_SECTOR_SIZE;
140 DBG2 ( "Get extended parameters: C/H/S = %d/%d/%d, sectors = %#08llx "
141 "(%d bytes)\n", disk_params->cylinders, disk_params->heads,
142 disk_params->sectors_per_track, disk_params->sectors,
143 disk_params->sector_size );
144
145 /* Success */
146 params->ah = 0;
147 }
148
149 /**
150 * INT 13, 42 - Extended read
151 *
152 * @v ds:si Disk address packet
153 * @ret ah Status code
154 */
155 static void int13_extended_read ( struct bootapp_callback_params *params ) {
156 struct int13_disk_address *disk_address;
157 void *data;
158
159 /* Read from emulated disk */
160 disk_address = REAL_PTR ( params->ds, params->si );
161 data = REAL_PTR ( disk_address->buffer.segment,
162 disk_address->buffer.offset );
163 vdisk_read ( disk_address->lba, disk_address->count, data );
164
165 /* Success */
166 params->ah = 0;
167 }
168
169 /**
170 * Emulate INT 13 drive
171 *
172 * @v params Parameters
173 */
174 void emulate_int13 ( struct bootapp_callback_params *params ) {
175 int command = params->ah;
176 int drive = params->dl;
177 int min_num_drives;
178 unsigned long eflags;
179
180 if ( drive == vdisk_drive ) {
181
182 /* Emulated drive - handle internally */
183
184 /* Populate eflags with a sensible starting value */
185 __asm__ ( "pushf\n\t"
186 "pop %0\n\t"
187 : "=r" ( eflags ) );
188 params->eflags = ( eflags & ~CF );
189
190 /* Handle command */
191 switch ( command ) {
192 case INT13_GET_PARAMETERS:
193 int13_get_parameters ( params );
194 break;
195 case INT13_GET_DISK_TYPE:
196 int13_get_disk_type ( params );
197 break;
198 case INT13_EXTENSION_CHECK:
199 int13_extension_check ( params );
200 break;
201 case INT13_GET_EXTENDED_PARAMETERS:
202 int13_get_extended_parameters ( params );
203 break;
204 case INT13_EXTENDED_READ:
205 int13_extended_read ( params );
206 break;
207 default:
208 DBG ( "Unrecognised INT 13,%02x\n", command );
209 params->eflags |= CF;
210 break;
211 }
212
213 } else {
214
215 /* Pass through command to underlying INT 13 */
216 call_interrupt ( params );
217
218 /* Modify drive count, if applicable */
219 if ( command == INT13_GET_PARAMETERS ) {
220 min_num_drives = ( ( vdisk_drive & 0x7f ) + 1 );
221 if ( params->dl < min_num_drives )
222 params->dl = min_num_drives;
223 }
224 }
225 }