3adac96c13c88725368ce743cc435fdbcbbe147d
[reactos.git] / reactos / drivers / setup / blue / font.c
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,
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 }