xref: /reactos/drivers/setup/blue/font.c (revision 845faec4)
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(UINT32 CodePage)
28 {
29     PHYSICAL_ADDRESS BaseAddress;
30     PUCHAR Bitplane;
31     PUCHAR FontBitfield = NULL;
32     NTSTATUS Status = STATUS_SUCCESS;
33 
34     FontBitfield = (PUCHAR) ExAllocatePoolWithTag(NonPagedPool, 2048, TAG_BLUE);
35     if(FontBitfield)
36     {
37         /* open bit plane for font table access */
38         OpenBitPlane();
39 
40         /* get pointer to video memory */
41         BaseAddress.QuadPart = BITPLANE_BASE;
42         Bitplane = (PUCHAR)MmMapIoSpace (BaseAddress, 0xFFFF, MmNonCached);
43 
44         Status = ExtractFont(CodePage, FontBitfield);
45         if (NT_SUCCESS(Status))
46             LoadFont(Bitplane, FontBitfield);
47 
48         MmUnmapIoSpace(Bitplane, 0xFFFF);
49         ExFreePool(FontBitfield);
50 
51         /* close bit plane */
52         CloseBitPlane();
53     }
54 }
55 
56 /* PRIVATE FUNCTIONS *********************************************************/
57 
58 NTSTATUS ExtractFont(UINT32 CodePage, PUCHAR FontBitField)
59 {
60     BOOLEAN            bFoundFile = FALSE;
61     HANDLE             Handle;
62     NTSTATUS           Status;
63     CHAR               FileName[20];
64     IO_STATUS_BLOCK    IoStatusBlock;
65     OBJECT_ATTRIBUTES  ObjectAttributes;
66     UNICODE_STRING     LinkName;
67     UNICODE_STRING     SourceName;
68     CFHEADER           CabFileHeader;
69     CFFILE             CabFile;
70     ULONG              CabFileOffset = 0;
71     LARGE_INTEGER      ByteOffset;
72     WCHAR              SourceBuffer[MAX_PATH] = {L'\0'};
73     ULONG              ReadCP;
74 
75     if(KeGetCurrentIrql() != PASSIVE_LEVEL)
76         return STATUS_INVALID_DEVICE_STATE;
77 
78     RtlInitUnicodeString(&LinkName,
79                          L"\\SystemRoot");
80 
81     InitializeObjectAttributes(&ObjectAttributes,
82                                &LinkName,
83                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
84                                NULL,
85                                NULL);
86 
87     Status = ZwOpenSymbolicLinkObject(&Handle,
88                                       SYMBOLIC_LINK_ALL_ACCESS,
89                                       &ObjectAttributes);
90 
91     if (!NT_SUCCESS(Status))
92         return(Status);
93 
94     SourceName.Length = 0;
95     SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR);
96     SourceName.Buffer = SourceBuffer;
97 
98     Status = ZwQuerySymbolicLinkObject(Handle,
99                                       &SourceName,
100                                       NULL);
101     ZwClose(Handle);
102 
103     Status = RtlAppendUnicodeToString(&SourceName, L"\\vgafonts.cab");
104     InitializeObjectAttributes(&ObjectAttributes, &SourceName,
105                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
106                                NULL, NULL);
107 
108     Status = ZwCreateFile(&Handle,
109                           GENERIC_READ,
110                           &ObjectAttributes, &IoStatusBlock, NULL,
111                           FILE_ATTRIBUTE_NORMAL,
112                           0,
113                           FILE_OPEN,
114                           FILE_SYNCHRONOUS_IO_NONALERT,
115                           NULL, 0);
116 
117     ByteOffset.LowPart = ByteOffset.HighPart = 0;
118 
119     if(NT_SUCCESS(Status))
120     {
121         Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock,
122                             &CabFileHeader, sizeof(CabFileHeader), &ByteOffset, NULL);
123 
124         if(NT_SUCCESS(Status))
125         {
126             if(CabFileHeader.Signature == CAB_SIGNATURE)
127             {
128                 // We have a valid CAB file!
129                 // Read the file table now and decrement the file count on every file. When it's zero, we read the complete table.
130                 ByteOffset.LowPart = CabFileHeader.FileTableOffset;
131 
132                 while(CabFileHeader.FileCount)
133                 {
134                     Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock,
135                                         &CabFile, sizeof(CabFile), &ByteOffset, NULL);
136 
137                     if(NT_SUCCESS(Status))
138                     {
139                         ByteOffset.LowPart += sizeof(CabFile);
140 
141                         // We assume here that the file name is max. 19 characters (+ 1 NULL character) long.
142                         // This should be enough for our purpose.
143                         Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock,
144                                             FileName, sizeof(FileName), &ByteOffset, NULL);
145 
146                         if(NT_SUCCESS(Status))
147                         {
148                             if(!bFoundFile)
149                             {
150                                 Status = RtlCharToInteger(FileName, 0, &ReadCP);
151                                 if (NT_SUCCESS(Status) && ReadCP == CodePage)
152                                 {
153                                     // We got the correct file.
154                                     // Save the offset and loop through the rest of the file table to find the position, where the actual data starts.
155                                     CabFileOffset = CabFile.FileOffset;
156                                     bFoundFile = TRUE;
157                                 }
158                             }
159 
160                             ByteOffset.LowPart += strlen(FileName) + 1;
161                         }
162                     }
163 
164                     CabFileHeader.FileCount--;
165                 }
166 
167                 // 8 = Size of a CFFOLDER structure (see cabman). As we don't need the values of that structure, just increase the offset here.
168                 ByteOffset.LowPart += 8;
169                 ByteOffset.LowPart += CabFileOffset;
170 
171                 // ByteOffset now contains the offset of the actual data, so we can read the RAW font
172                 Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock,
173                                     FontBitField, 2048, &ByteOffset, NULL);
174                 ZwClose(Handle);
175                 return STATUS_SUCCESS;
176             }
177             else
178             {
179                 DPRINT1("Error: CAB signature is missing!\n");
180                 Status = STATUS_UNSUCCESSFUL;
181             }
182         }
183         else
184             DPRINT1("Error: Cannot read from file\n");
185 
186         ZwClose(Handle);
187         return Status;
188     }
189     else
190     {
191         DPRINT1("Error: Cannot open vgafonts.cab\n");
192         return Status;
193     }
194 }
195 
196 /* Font-load specific funcs */
197 VOID
198 OpenBitPlane(VOID)
199 {
200     /* disable interrupts */
201     _disable();
202 
203     /* sequence reg */
204     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR (SEQ_DATA, 0x01);
205     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_ENABLE_WRT_PLANE); WRITE_PORT_UCHAR (SEQ_DATA, 0x04);
206     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_MEM_MODE); WRITE_PORT_UCHAR (SEQ_DATA, 0x07);
207     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR (SEQ_DATA, 0x03);
208 
209     /* graphic reg */
210     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_READ_PLANE); WRITE_PORT_UCHAR (GCT_DATA, 0x02);
211     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_RW_MODES); WRITE_PORT_UCHAR (GCT_DATA, 0x00);
212     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_GRAPH_MODE); WRITE_PORT_UCHAR (GCT_DATA, 0x00);
213 
214     /* enable interrupts */
215     _enable();
216 }
217 
218 VOID
219 CloseBitPlane(VOID)
220 {
221     /* disable interrupts */
222     _disable();
223 
224     /* sequence reg */
225     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR (SEQ_DATA, 0x01);
226     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_ENABLE_WRT_PLANE); WRITE_PORT_UCHAR (SEQ_DATA, 0x03);
227     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_MEM_MODE); WRITE_PORT_UCHAR (SEQ_DATA, 0x03);
228     WRITE_PORT_UCHAR (SEQ_COMMAND, SEQ_RESET); WRITE_PORT_UCHAR (SEQ_DATA, 0x03);
229 
230     /* graphic reg */
231     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_READ_PLANE); WRITE_PORT_UCHAR (GCT_DATA, 0x00);
232     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_RW_MODES); WRITE_PORT_UCHAR (GCT_DATA, 0x10);
233     WRITE_PORT_UCHAR (GCT_COMMAND, GCT_GRAPH_MODE); WRITE_PORT_UCHAR (GCT_DATA, 0x0e);
234 
235     /* enable interrupts */
236     _enable();
237 }
238 
239 VOID
240 LoadFont(PUCHAR Bitplane, PUCHAR FontBitfield)
241 {
242     UINT32 i,j;
243 
244     for (i=0; i<256; i++)
245     {
246         for (j=0; j<8; j++)
247         {
248             *Bitplane = FontBitfield[i*8+j];
249             Bitplane++;
250         }
251 
252         // padding
253         for (j=8; j<32; j++)
254         {
255             *Bitplane = 0;
256             Bitplane++;
257         }
258     }
259 }
260