1 /* 2 * PROJECT: ReactOS Setup Driver 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/setup/blue/font.c 5 * PURPOSE: Loading specific fonts into VGA 6 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) 7 * Colin Finck (mail@colinfinck.de) 8 * Christoph von Wittich (christoph_vw@reactos.org) 9 */ 10 11 /* INCLUDES ***************************************************************/ 12 13 #include "blue.h" 14 15 #include <ntddk.h> 16 17 #define NDEBUG 18 #include <debug.h> 19 20 VOID OpenBitPlane(); 21 VOID CloseBitPlane(); 22 VOID LoadFont(PUCHAR Bitplane, PUCHAR FontBitfield); 23 24 /* FUNCTIONS ****************************************************************/ 25 26 VOID 27 ScrLoadFontTable( 28 UINT32 CodePage) 29 { 30 PHYSICAL_ADDRESS BaseAddress; 31 PUCHAR Bitplane; 32 PUCHAR FontBitfield = NULL; 33 NTSTATUS Status = STATUS_SUCCESS; 34 35 FontBitfield = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_BLUE); 36 if (FontBitfield == NULL) 37 { 38 DPRINT1("ExAllocatePoolWithTag failed\n"); 39 return; 40 } 41 42 /* open bit plane for font table access */ 43 OpenBitPlane(); 44 45 /* get pointer to video memory */ 46 BaseAddress.QuadPart = BITPLANE_BASE; 47 Bitplane = (PUCHAR)MmMapIoSpace(BaseAddress, 0xFFFF, MmNonCached); 48 49 Status = ExtractFont(CodePage, FontBitfield); 50 if (NT_SUCCESS(Status)) 51 { 52 LoadFont(Bitplane, FontBitfield); 53 } 54 else 55 { 56 DPRINT1("ExtractFont failed with Status 0x%lx\n", Status); 57 } 58 59 MmUnmapIoSpace(Bitplane, 0xFFFF); 60 ExFreePool(FontBitfield); 61 62 /* close bit plane */ 63 CloseBitPlane(); 64 } 65 66 /* PRIVATE FUNCTIONS *********************************************************/ 67 68 NTSTATUS 69 ExtractFont( 70 UINT32 CodePage, 71 PUCHAR FontBitField) 72 { 73 BOOLEAN bFoundFile = FALSE; 74 HANDLE Handle; 75 NTSTATUS Status; 76 CHAR FileName[20]; 77 IO_STATUS_BLOCK IoStatusBlock; 78 OBJECT_ATTRIBUTES ObjectAttributes; 79 UNICODE_STRING LinkName; 80 UNICODE_STRING SourceName; 81 CFHEADER CabFileHeader; 82 CFFILE CabFile; 83 ULONG CabFileOffset = 0; 84 LARGE_INTEGER ByteOffset; 85 WCHAR SourceBuffer[MAX_PATH] = { L'\0' }; 86 ULONG ReadCP; 87 88 if (KeGetCurrentIrql() != PASSIVE_LEVEL) 89 return STATUS_INVALID_DEVICE_STATE; 90 91 RtlInitUnicodeString(&LinkName, 92 L"\\SystemRoot"); 93 94 InitializeObjectAttributes(&ObjectAttributes, 95 &LinkName, 96 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 97 NULL, 98 NULL); 99 100 Status = ZwOpenSymbolicLinkObject(&Handle, 101 SYMBOLIC_LINK_ALL_ACCESS, 102 &ObjectAttributes); 103 104 if (!NT_SUCCESS(Status)) 105 { 106 DPRINT1("ZwOpenSymbolicLinkObject failed with Status 0x%lx\n", Status); 107 return Status; 108 } 109 110 SourceName.Length = 0; 111 SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR); 112 SourceName.Buffer = SourceBuffer; 113 114 Status = ZwQuerySymbolicLinkObject(Handle, 115 &SourceName, 116 NULL); 117 ZwClose(Handle); 118 119 if (!NT_SUCCESS(Status)) 120 { 121 DPRINT1("ZwQuerySymbolicLinkObject failed with Status 0x%lx\n", Status); 122 return Status; 123 } 124 125 Status = RtlAppendUnicodeToString(&SourceName, L"\\vgafonts.cab"); 126 if (!NT_SUCCESS(Status)) 127 { 128 DPRINT1("RtlAppendUnicodeToString failed with Status 0x%lx\n", Status); 129 return Status; 130 } 131 132 InitializeObjectAttributes(&ObjectAttributes, 133 &SourceName, 134 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 135 NULL, 136 NULL); 137 138 Status = ZwCreateFile(&Handle, 139 GENERIC_READ, 140 &ObjectAttributes, 141 &IoStatusBlock, 142 NULL, 143 FILE_ATTRIBUTE_NORMAL, 144 0, 145 FILE_OPEN, 146 FILE_SYNCHRONOUS_IO_NONALERT, 147 NULL, 148 0); 149 if (!NT_SUCCESS(Status)) 150 { 151 DPRINT1("Error: Cannot open vgafonts.cab (0x%lx)\n", Status); 152 return Status; 153 } 154 155 ByteOffset.QuadPart = 0; 156 Status = ZwReadFile(Handle, 157 NULL, 158 NULL, 159 NULL, 160 &IoStatusBlock, 161 &CabFileHeader, 162 sizeof(CabFileHeader), 163 &ByteOffset, 164 NULL); 165 166 if (!NT_SUCCESS(Status)) 167 { 168 DPRINT1("Error: Cannot read from file (0x%lx)\n", Status); 169 goto Exit; 170 } 171 172 if (CabFileHeader.Signature != CAB_SIGNATURE) 173 { 174 DPRINT1("Invalid CAB signature: 0x%lx!\n", CabFileHeader.Signature); 175 Status = STATUS_UNSUCCESSFUL; 176 goto Exit; 177 } 178 179 // We have a valid CAB file! 180 // Read the file table now and decrement the file count on every file. When it's zero, we read the complete table. 181 ByteOffset.QuadPart = CabFileHeader.FileTableOffset; 182 183 while (CabFileHeader.FileCount) 184 { 185 Status = ZwReadFile(Handle, 186 NULL, 187 NULL, 188 NULL, 189 &IoStatusBlock, 190 &CabFile, 191 sizeof(CabFile), 192 &ByteOffset, 193 NULL); 194 195 if (NT_SUCCESS(Status)) 196 { 197 ByteOffset.QuadPart += sizeof(CabFile); 198 199 // We assume here that the file name is max. 19 characters (+ 1 NULL character) long. 200 // This should be enough for our purpose. 201 Status = ZwReadFile(Handle, 202 NULL, 203 NULL, 204 NULL, 205 &IoStatusBlock, 206 FileName, 207 sizeof(FileName), 208 &ByteOffset, 209 NULL); 210 211 if (NT_SUCCESS(Status)) 212 { 213 if (!bFoundFile) 214 { 215 Status = RtlCharToInteger(FileName, 0, &ReadCP); 216 if (NT_SUCCESS(Status) && ReadCP == CodePage) 217 { 218 // We got the correct file. 219 // Save the offset and loop through the rest of the file table to find the position, where the actual data starts. 220 CabFileOffset = CabFile.FileOffset; 221 bFoundFile = TRUE; 222 } 223 } 224 225 ByteOffset.QuadPart += strlen(FileName) + 1; 226 } 227 } 228 229 CabFileHeader.FileCount--; 230 } 231 232 // 8 = Size of a CFFOLDER structure (see cabman). As we don't need the values of that structure, just increase the offset here. 233 ByteOffset.QuadPart += 8; 234 ByteOffset.QuadPart += CabFileOffset; 235 236 // ByteOffset now contains the offset of the actual data, so we can read the RAW font 237 Status = ZwReadFile(Handle, 238 NULL, 239 NULL, 240 NULL, 241 &IoStatusBlock, 242 FontBitField, 243 2048, 244 &ByteOffset, 245 NULL); 246 if (!NT_SUCCESS(Status)) 247 { 248 DPRINT1("ZwReadFile failed with Status 0x%lx\n", Status); 249 } 250 251 Exit: 252 253 ZwClose(Handle); 254 return Status; 255 } 256 257 /* Font-load specific funcs */ 258 VOID 259 OpenBitPlane(VOID) 260 { 261 /* disable interrupts */ 262 _disable(); 263 264 /* sequence reg */ 265 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR(SEQ_DATA, 0x01); 266 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_ENABLE_WRT_PLANE); WRITE_PORT_UCHAR(SEQ_DATA, 0x04); 267 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_MEM_MODE); WRITE_PORT_UCHAR(SEQ_DATA, 0x07); 268 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR(SEQ_DATA, 0x03); 269 270 /* graphic reg */ 271 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_READ_PLANE); WRITE_PORT_UCHAR(GCT_DATA, 0x02); 272 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_RW_MODES); WRITE_PORT_UCHAR(GCT_DATA, 0x00); 273 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_GRAPH_MODE); WRITE_PORT_UCHAR(GCT_DATA, 0x00); 274 275 /* enable interrupts */ 276 _enable(); 277 } 278 279 VOID 280 CloseBitPlane(VOID) 281 { 282 /* disable interrupts */ 283 _disable(); 284 285 /* sequence reg */ 286 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR(SEQ_DATA, 0x01); 287 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_ENABLE_WRT_PLANE); WRITE_PORT_UCHAR(SEQ_DATA, 0x03); 288 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_MEM_MODE); WRITE_PORT_UCHAR(SEQ_DATA, 0x03); 289 WRITE_PORT_UCHAR(SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR(SEQ_DATA, 0x03); 290 291 /* graphic reg */ 292 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_READ_PLANE); WRITE_PORT_UCHAR(GCT_DATA, 0x00); 293 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_RW_MODES); WRITE_PORT_UCHAR(GCT_DATA, 0x10); 294 WRITE_PORT_UCHAR(GCT_COMMAND, GCT_GRAPH_MODE); WRITE_PORT_UCHAR(GCT_DATA, 0x0e); 295 296 /* enable interrupts */ 297 _enable(); 298 } 299 300 VOID 301 LoadFont( 302 PUCHAR Bitplane, 303 PUCHAR FontBitfield) 304 { 305 UINT32 i, j; 306 307 for (i = 0; i < 256; i++) 308 { 309 for (j = 0; j < 8; j++) 310 { 311 *Bitplane = FontBitfield[i * 8 + j]; 312 Bitplane++; 313 } 314 315 // padding 316 for (j = 8; j < 32; j++) 317 { 318 *Bitplane = 0; 319 Bitplane++; 320 } 321 } 322 } 323