2 * PROJECT: ReactOS Console Text-Mode Device Driver
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Loading specific fonts into VGA.
5 * COPYRIGHT: Copyright 2008-2019 Aleksey Bragin (aleksey@reactos.org)
6 * Copyright 2008-2019 Colin Finck (mail@colinfinck.de)
7 * Copyright 2008-2019 Christoph von Wittich (christoph_vw@reactos.org)
10 /* INCLUDES ***************************************************************/
13 #include <ndk/rtlfuncs.h>
18 NTSTATUS
ExtractFont(_In_ ULONG CodePage
, _In_ PUCHAR FontBitField
);
19 VOID
OpenBitPlane(VOID
);
20 VOID
CloseBitPlane(VOID
);
21 VOID
LoadFont(_In_ PUCHAR Bitplane
, _In_ PUCHAR FontBitfield
);
23 /* FUNCTIONS ****************************************************************/
29 PHYSICAL_ADDRESS BaseAddress
;
31 PUCHAR FontBitfield
= NULL
;
32 NTSTATUS Status
= STATUS_SUCCESS
;
34 FontBitfield
= (PUCHAR
)ExAllocatePoolWithTag(NonPagedPool
, 2048, TAG_BLUE
);
35 if (FontBitfield
== NULL
)
37 DPRINT1("ExAllocatePoolWithTag failed\n");
41 /* open bit plane for font table access */
44 /* get pointer to video memory */
45 BaseAddress
.QuadPart
= BITPLANE_BASE
;
46 Bitplane
= (PUCHAR
)MmMapIoSpace(BaseAddress
, 0xFFFF, MmNonCached
);
48 Status
= ExtractFont(CodePage
, FontBitfield
);
49 if (NT_SUCCESS(Status
))
51 LoadFont(Bitplane
, FontBitfield
);
55 DPRINT1("ExtractFont failed with Status 0x%lx\n", Status
);
58 MmUnmapIoSpace(Bitplane
, 0xFFFF);
59 ExFreePoolWithTag(FontBitfield
, TAG_BLUE
);
67 _In_ PUCHAR FontBitfield
)
69 PHYSICAL_ADDRESS BaseAddress
;
72 /* open bit plane for font table access */
75 /* get pointer to video memory */
76 BaseAddress
.QuadPart
= BITPLANE_BASE
;
77 Bitplane
= (PUCHAR
)MmMapIoSpace(BaseAddress
, 0xFFFF, MmNonCached
);
79 LoadFont(Bitplane
, FontBitfield
);
81 MmUnmapIoSpace(Bitplane
, 0xFFFF);
87 /* PRIVATE FUNCTIONS *********************************************************/
92 _In_ PUCHAR FontBitField
)
94 BOOLEAN bFoundFile
= FALSE
;
98 IO_STATUS_BLOCK IoStatusBlock
;
99 OBJECT_ATTRIBUTES ObjectAttributes
;
100 UNICODE_STRING LinkName
;
101 UNICODE_STRING SourceName
;
102 CFHEADER CabFileHeader
;
104 ULONG CabFileOffset
= 0;
105 LARGE_INTEGER ByteOffset
;
106 WCHAR SourceBuffer
[MAX_PATH
] = { L
'\0' };
109 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
110 return STATUS_INVALID_DEVICE_STATE
;
112 RtlInitUnicodeString(&LinkName
,
115 InitializeObjectAttributes(&ObjectAttributes
,
117 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
121 Status
= ZwOpenSymbolicLinkObject(&Handle
,
122 SYMBOLIC_LINK_ALL_ACCESS
,
125 if (!NT_SUCCESS(Status
))
127 DPRINT1("ZwOpenSymbolicLinkObject failed with Status 0x%lx\n", Status
);
131 SourceName
.Length
= 0;
132 SourceName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
133 SourceName
.Buffer
= SourceBuffer
;
135 Status
= ZwQuerySymbolicLinkObject(Handle
,
140 if (!NT_SUCCESS(Status
))
142 DPRINT1("ZwQuerySymbolicLinkObject failed with Status 0x%lx\n", Status
);
146 Status
= RtlAppendUnicodeToString(&SourceName
, L
"\\vgafonts.cab");
147 if (!NT_SUCCESS(Status
))
149 DPRINT1("RtlAppendUnicodeToString failed with Status 0x%lx\n", Status
);
153 InitializeObjectAttributes(&ObjectAttributes
,
155 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
159 Status
= ZwCreateFile(&Handle
,
164 FILE_ATTRIBUTE_NORMAL
,
167 FILE_SYNCHRONOUS_IO_NONALERT
,
170 if (!NT_SUCCESS(Status
))
172 DPRINT1("Error: Cannot open vgafonts.cab (0x%lx)\n", Status
);
176 ByteOffset
.QuadPart
= 0;
177 Status
= ZwReadFile(Handle
,
183 sizeof(CabFileHeader
),
187 if (!NT_SUCCESS(Status
))
189 DPRINT1("Error: Cannot read from file (0x%lx)\n", Status
);
193 if (CabFileHeader
.Signature
!= CAB_SIGNATURE
)
195 DPRINT1("Invalid CAB signature: 0x%lx!\n", CabFileHeader
.Signature
);
196 Status
= STATUS_UNSUCCESSFUL
;
200 // We have a valid CAB file!
201 // Read the file table now and decrement the file count on every file. When it's zero, we read the complete table.
202 ByteOffset
.QuadPart
= CabFileHeader
.FileTableOffset
;
204 while (CabFileHeader
.FileCount
)
206 Status
= ZwReadFile(Handle
,
216 if (NT_SUCCESS(Status
))
218 ByteOffset
.QuadPart
+= sizeof(CabFile
);
220 // We assume here that the file name is max. 19 characters (+ 1 NULL character) long.
221 // This should be enough for our purpose.
222 Status
= ZwReadFile(Handle
,
232 if (NT_SUCCESS(Status
))
236 Status
= RtlCharToInteger(FileName
, 0, &ReadCP
);
237 if (NT_SUCCESS(Status
) && ReadCP
== CodePage
)
239 // We got the correct file.
240 // Save the offset and loop through the rest of the file table to find the position, where the actual data starts.
241 CabFileOffset
= CabFile
.FileOffset
;
246 ByteOffset
.QuadPart
+= strlen(FileName
) + 1;
250 CabFileHeader
.FileCount
--;
253 // 8 = Size of a CFFOLDER structure (see cabman). As we don't need the values of that structure, just increase the offset here.
254 ByteOffset
.QuadPart
+= 8;
255 ByteOffset
.QuadPart
+= CabFileOffset
;
257 // ByteOffset now contains the offset of the actual data, so we can read the RAW font
258 Status
= ZwReadFile(Handle
,
267 if (!NT_SUCCESS(Status
))
269 DPRINT1("ZwReadFile failed with Status 0x%lx\n", Status
);
278 /* Font-load specific funcs */
282 /* disable interrupts */
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
, 0x04);
288 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_MEM_MODE
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x07);
289 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_RESET
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x03);
292 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_READ_PLANE
); WRITE_PORT_UCHAR(GCT_DATA
, 0x02);
293 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_RW_MODES
); WRITE_PORT_UCHAR(GCT_DATA
, 0x00);
294 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_GRAPH_MODE
); WRITE_PORT_UCHAR(GCT_DATA
, 0x00);
296 /* enable interrupts */
303 /* disable interrupts */
307 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_RESET
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x01);
308 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_ENABLE_WRT_PLANE
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x03);
309 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_MEM_MODE
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x03);
310 WRITE_PORT_UCHAR(SEQ_COMMAND
, SEQ_RESET
); WRITE_PORT_UCHAR(SEQ_DATA
, 0x03);
313 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_READ_PLANE
); WRITE_PORT_UCHAR(GCT_DATA
, 0x00);
314 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_RW_MODES
); WRITE_PORT_UCHAR(GCT_DATA
, 0x10);
315 WRITE_PORT_UCHAR(GCT_COMMAND
, GCT_GRAPH_MODE
); WRITE_PORT_UCHAR(GCT_DATA
, 0x0e);
317 /* enable interrupts */
323 _In_ PUCHAR Bitplane
,
324 _In_ PUCHAR FontBitfield
)
328 for (i
= 0; i
< 256; i
++)
330 for (j
= 0; j
< 8; j
++)
332 *Bitplane
= FontBitfield
[i
* 8 + j
];
337 for (j
= 8; j
< 32; j
++)