source: trunk/install/c/install.c-cid-quirk@ 57

Last change on this file since 57 was 57, checked in by Ben Rietbroek, 10 years ago

All source-files lowercased [v1.1.1-testing]

Some standard files like 'COPYING', 'LICENSE', etc. have not been
converted to lower case because they are usually distributed uppercased.

File size: 67.2 KB
Line 
1// AiR-BOOT (c) Copyright 1998-2009 M. Kiewitz
2//
3// This file is part of AiR-BOOT
4//
5// AiR-BOOT is free software: you can redistribute it and/or modify it under
6// the terms of the GNU General Public License as published by the Free
7// Software Foundation, either version 3 of the License, or (at your option)
8// any later version.
9//
10// AiR-BOOT is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY: without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13// details.
14//
15// You should have received a copy of the GNU General Public License along with
16// AiR-BOOT. If not, see <http://www.gnu.org/licenses/>.
17//
18
19
20
21#include "INSTALL.H"
22
23
24
25// ============================================================================
26// Variables
27// ============================================================================
28
29
30
31//CHAR Track0[SECTOR_COUNT * BYTES_PER_SECTOR]; // current track 0 from harddrive
32//CHAR Bootcode[SECTOR_COUNT * BYTES_PER_SECTOR]; // bootcode image from airboot.bin
33
34/*
35// With the addition of the C DOS-version, a static buffer for both
36// Track0 and Bootcode would overflow the DGROUP segment. (>64kB)
37// Placing the buffers in another segment does not work with Open Watcom v1.9.
38// While the buffers are BSS and should be in segments like FAR_BSS,
39// Open Watcom places the buffers in FAR_DATA and produces a bloated DOS
40// executable. Using the same source and then building an OS/2 v1.x
41// executable does not produce a bloated .EXE, eventhough the segments are
42// called FAR_DATA and in the middle of the image.
43// Microsoft C v6.0 displays the same behavior; DOS bloated, OS/2 v1.x ok.
44// An interesting feat is that when building an OS/2 v1.x executable and then
45// binding that to produce a FAPI executable does not produce a bloated .EXE
46//
47// Also, when experimenting with segments and #pragma data_seg(), some
48// strange behavior was observed.
49// WCC:
50// Explicitly naming a segment and class for the static buffers caused
51// wcc to keep generating it's default SS: based addressing, eventhough
52// the segments are not part of DGROUP.
53// Only the -zu flag corrects this. (DS!=SS)
54// WPP:
55// C++ wpp used correct addressing but the segment class in the #pragma
56// was not honored and the segment name got mangled.
57//
58// In both cases the volatile (transient) data would occupy space in the
59// disk-image.
60// The only way seems to be putting the buffers in a separate segment using
61// pragma's, using wcc with the -zu flag and use the wlink ORDER directive
62// to place the FAR BSS data above the stack acompanied by a NOEMIT modifier.
63// For this all the class names of the previous segments must be included
64// in the wlink ORDER directive which would make the link phase dependend
65// on segment names. This solution does not work for wpp because it mangles
66// the segment name and overrides the custom class name to FAR_DATA.
67//
68// So, these buffers are now dynamically allocated.
69*/
70PCHAR Track0 = NULL; // Buffer for Track0 from harddisk.
71PCHAR Bootcode = NULL; // Buffer for AIRBOOT.BIN image.
72
73UCHAR Bootcode_LanguageID = ' ';
74USHORT Bootcode_Version = 0;
75USHORT Bootcode_ConfigVersion = 0;
76
77UCHAR Status_Code = STATUS_NOTINSTALLED;
78UCHAR Status_Config = STATUS_NOTINSTALLED;
79USHORT Installed_CodeVersion = 0;
80USHORT Installed_ConfigVersion = 0;
81UCHAR Installed_LanguageID = ' ';
82
83BOOL Option_ForceCode = FALSE;
84BOOL Option_ForceConfig = FALSE;
85BOOL Option_Silent = FALSE;
86BOOL Option_CID = FALSE;
87
88BOOL Install_Code = FALSE;
89BOOL Install_Config = FALSE;
90BOOL Install_IsCorrupt = FALSE;
91
92//USHORT StatusCode = 0;
93PSZ ImpossibleCause = NULL;
94
95CHAR TempHidPartTable[45 * 34];
96
97
98
99
100// ============================================================================
101// Kidnapped bitfield functions needed to access the packed hideparttable
102// ============================================================================
103
104/*
105// Pragma's could be used to interface with the bitfield functions, but I was
106// not in the mood to examine how they behave when conditions like calling
107// convention, memory model, optimization, etc. are changed. Especially
108// optimization generates very different code depending on the -o flags so
109// it felt a bit 'fragile' to me to use them without further analysis.
110// So I opted for the 'easy way' of some small prolog code to pass the
111// parameters to the correct registers required by the core bitfield functions.
112*/
113
114
115//~ #ifdef __386__
116//~ #pragma aux __airboot "*___" parm caller [EBX] [EDX] [ECX] [EAX ESI EDI] value [AL];
117//~ #else
118//~ #pragma aux __airboot "*___" parm caller [DI BX] [DX] [CX] [AX SI] value [AL];
119//~ #endif
120//~ #pragma aux (__airboot) get_bitfield;
121//~ #pragma aux (__airboot) set_bitfield;
122
123/* Prototypes */
124void bf_test();
125char get_bitfield(char* buffer, char index, char fieldwidth);
126char set_bitfield(char* buffer, char index, char fieldwidth, char value);
127
128//~ #ifdef __386__
129//~ #pragma aux get_bitfield parm [EBX] [ECX] [EDX] value [AL];
130//~ #pragma aux set_bitfield parm [EBX] [ECX] [EDX] [EAX];
131//~ #else
132//~ #pragma aux get_bitfield value [DL];
133//~ #pragma aux set_bitfield parm [BX] [CX] [DX] [AX];
134//~ #endif
135
136void DumpTrack0();
137
138// In 32-bit mode EBX is used and in 16-bit mode BX, so we abstract it's name.
139// The rest of the bitfield code uses 16-bit registers because I kidnapped
140// it from AiR-BOOT.
141#define dataptr16 "BX"
142#define dataptr32 "EBX"
143#ifdef __386__
144 #define dataptr dataptr32
145#else
146 #define dataptr dataptr16
147#endif
148
149
150
151
152/*
153// ----------------------------------------------------------------------------
154// bf_test -- Test function to analyse code generation
155// ----------------------------------------------------------------------------
156*/
157void bf_test() {
158 char* b1 = Track0;
159 char* b2 = Bootcode;
160 char i1 = 0x11;
161 char i2 = 0x12;
162 char v1 = 0x83;
163 char v2 = 0x84;
164 char rv1 = 0xf8;
165 char rv2 = 0xf9;
166
167 rv1 = get_bitfield(b1, i1, 6);
168 rv2 = set_bitfield(b2, i2, 6, v1+v2);
169}
170
171/*
172// ----------------------------------------------------------------------------
173// do_bf_test -- Simple function to test the bitfield functions
174// ----------------------------------------------------------------------------
175*/
176void do_bf_test() {
177 char buf[512];
178 int i;
179
180 for (i=0; i<100; i++) {
181 set_bitfield(buf, i, 6, i);
182 }
183
184 set_bitfield(buf, 18, 6, 255);
185 set_bitfield(buf, 21, 6, 255);
186 set_bitfield(buf, 33, 6, 255);
187 set_bitfield(buf, 37, 6, 255);
188
189
190 for (i=0; i<100; i++) {
191 printf("index: %02d, value: %02d\n", i, get_bitfield(buf, i, 6));
192 }
193 return;
194}
195
196
197/*
198// ----------------------------------------------------------------------------
199// get_bitfield -- Get a n-bit wide bitfield at index i from a buffer in memory
200// ----------------------------------------------------------------------------
201// This is code kidnapped from AiR-BOOT and used here to handle the packed
202// hideparttable. A 'record' in the hideparttable is 34 bytes long and it
203// can store 45 partition numbers using 6-bits per partition number.
204// Bitfield widths from 1 to 8 are supported and the maximum buffersize is
205// 256 bytes.
206*/
207char get_bitfield(char* buffer, char index, char fieldwidth) {
208
209 char rv = 0;
210 // These are used to break-up the far pointer in large-data model 16-bit
211 // code so the buffer can be addressed correctly.
212 // In 32-bit flat mode they will have no effect and in 32-bit large-data
213 // mode (imaginary) they can handle the buffer being in a seperate segment.
214 unsigned dseg = _FP_SEG(buffer);
215 unsigned dptr = _FP_OFF(buffer);
216
217 // Prolog code.
218 // Handle data-segment and parameters.
219 _asm {
220 push ds ; Save DS from caller.
221 push dseg ; Setup DS to
222 pop ds ; address our segment. (When 16-bit large data-model)
223
224 mov dl, index ; Index to bitfield in DL.
225 mov dh, fieldwidth ; Width of bitfield in DH.
226 mov dataptr, dptr ; Pointer in [E]BX.
227 }
228
229
230 // This is practically a verbatim copy of the core routine from CONV.ASM.
231 // Only a slight modification with regard to [E]BX addressing is made
232 // so it can also function in 32-bit mode.
233 _asm {
234
235 ; IN: DL = Index to store bitfield
236 ; DH = Bitfield width (1-8)
237 ; [E]BX = Pointer to bitfield array
238 ; OUT: AL = Value of requested bitfield
239 ; AH = Mask value
240
241 ; Normalize bit-width in DH.
242 dec dh ; Decrement bitfield width to mask invalid values.
243 and dh,07h ; Only 3 bits are significant to determine width.
244 mov cl,dh ; Save for later use to calculate mask.
245 inc dh ; Put back to normalized value.
246
247 ; Calculate corresponding AND-mask in CH.
248 mov ch,2 ; Were going to shift 2...
249 shl ch,cl ; to obtain the mask corresponding...
250 dec ch ; to the bitfield width.
251
252 ; Calculate byte-index.
253 mov al,dl ; Index in AL.
254 inc al ; Increment for calculations.
255 mul dh ; Multiply by bitfield width to get bits.
256 mov cl,8 ; Nr. of bits in a byte.
257 div cl ; Divide to get byte index.
258
259 ; Advance pointer to byte-index.
260 add bl,al ; Advance pointer...
261 adc bh,0 ; to byte index.
262
263 ; We have to 'carry on' to the high word of EBX if in 32-bit mode.
264#ifdef __386__
265 pushf ; Save the possible carry from the last addition.
266 ror ebx,16 ; Get high word of EBX in BX.
267 popf ; Restore possible carry.
268 adc bx,0 ; Add it and...
269 rol ebx,16 ; move back to have a valid 32-bit pointer again.
270#endif
271
272 ; Determine if we need 1 or 2 byte access to extract the bitfield.
273 mov cl,ah ; Get remainder in CL.
274 sub cl,dh ; Substract bitfield width to get shift-count.
275 mov ah,0 ; Prepare upper=0 when field spans no byte bound.
276 ; Don't change to xor ah,ah or any CY will be lost.
277
278 ; Jump if the bitfield does not span byte boundaries.
279 ; (Remainder - bitfield width >= 0)
280 jae CONV_GetBitfieldValue_nospan
281
282 ; Bit-field spans byte boundaries, so adjust shift-count
283 ; and use AH to get first part of bitfield.
284 add cl,8 ; Adjust shift-count.
285 mov ah,[dataptr] ; Get byte into AH instead.
286 dec dataptr ; Adjust pointer to load rest of bitfield.
287
288 CONV_GetBitfieldValue_nospan:
289 mov al,[dataptr] ; Load (rest of) bitfield into AL.
290 shr ax,cl ; Shift bitfield to the right.
291 mov ah,ch ; Get mask in AH.
292 and al,ah ; Mask value.
293 }
294
295
296 // Epilog code.
297 // Restore caller's DS.
298 // Store return value.
299 _asm {
300 pop ds
301 mov [rv],al
302 }
303
304 return rv;
305}
306
307
308/*
309// ----------------------------------------------------------------------------
310// set_bitfield -- Set a n-bit wide bitfield at index i in a buffer in memory
311// ----------------------------------------------------------------------------
312// This is code kidnapped from AiR-BOOT and used here to handle the packed
313// hideparttable. A 'record' in the hideparttable is 34 bytes long and it
314// can store 45 partition numbers using 6-bits per partition number.
315// Bitfield widths from 1 to 8 are supported and the maximum buffersize is
316// 256 bytes.
317*/
318char set_bitfield(char* buffer, char index, char fieldwidth, char value) {
319
320
321 // These are used to break-up the far pointer in large-data model 16-bit
322 // code so the buffer can be addressed correctly.
323 // In 32-bit flat mode they will have no effect and in 32-bit large-data
324 // mode (imaginary) they can handle the buffer being in a seperate segment.
325 unsigned dseg = _FP_SEG(buffer);
326 unsigned dptr = _FP_OFF(buffer);
327
328 // Prolog code.
329 // Handle data-segment and parameters.
330 _asm {
331 push ds ; Save DS from caller.
332 push dseg ; Setup DS to
333 pop ds ; address our segment. (When 16-bit large data-model)
334
335 mov dl, index ; Index to bitfield in DL.
336 mov dh, fieldwidth ; Width of bitfield in DH.
337 mov dataptr, dptr ; Pointer in [E]BX.
338 mov al, value ; Value we want to poke in AL.
339 }
340
341
342 // This is practically a verbatim copy of the core routine from CONV.ASM.
343 // Only a slight modification with regard to [E]BX addressing is made
344 // so it can also function in 32-bit mode.
345 _asm {
346
347 ; IN: AL = Value to store
348 ; DL = Index to store bitfield
349 ; DH = Bitfield width (1-8)
350 ; [E]BX = Pointer to bitfield array
351 ; OUT: AL = Value of stored bitfield
352 ; AH = Mask value
353
354 ; Push value for later use.
355 push ax
356
357 ; Normalize bit-width in DH.
358 dec dh ; Decrement bitfield width to mask invalid values.
359 and dh,07h ; Only 3 bits are significant to determine width.
360 mov cl,dh ; Save for later use to calculate mask.
361 inc dh ; Put back to normalized value.
362
363 ; Calculate corresponding AND-mask in CH.
364 mov ch,2 ; Were going to shift 2...
365 shl ch,cl ; to obtain the mask corresponding...
366 dec ch ; to the bitfield width.
367
368 ; Calculate byte-index.
369 mov al,dl ; Index in AL.
370 inc al ; Increment for calculations.
371 mul dh ; Multiply by bitfield width to get bits.
372 mov cl,8 ; Nr. of bits in a byte.
373 div cl ; Divide to get byte index.
374
375 ; Advance pointer to byte-index.
376 add bl,al ; Advance pointer...
377 adc bh,0 ; to byte index.
378
379 ; We have to 'carry on' to the high word of EBX if in 32-bit mode.
380#ifdef __386__
381 pushf ; Save the possible carry from the last addition.
382 ror ebx,16 ; Get high word of EBX in BX.
383 popf ; Restore possible carry.
384 adc bx,0 ; Add it and...
385 rol ebx,16 ; move back to have a valid 32-bit pointer again.
386#endif
387
388 ; Determine if we need 1 or 2 byte access to extract the bitfield.
389 mov cl,ah ; Get remainder in CL.
390 sub cl,dh ; Substract bitfield width to get shift-count.
391
392 ; Restore value to poke.
393 pop ax
394
395
396 ; Jump if the bitfield does not span byte boundaries.
397 ; (Remainder - bitfield width >= 0)
398 jae CONV_SetBitfieldValue_nospan
399
400 ; Bit-field spans byte boundaries, so adjust shift-count
401 ; and use 16-bit access.
402 add cl,8 ; Adjust shift-count.
403
404 ; Merge the bitfield to the array.
405 push cx ; Save mask (CH) and shift-count (CL).
406 push ax ; Save value to store.
407 xor ah,ah ; Clear upper byte so we can shift in it.
408 and al,ch ; Mask value.
409 shl ax,cl ; Move the bitfield to the proper location.
410 mov dh,[dataptr] ; Get 1st part of bitfield from array.
411 dec dataptr ; Adjust pointer.
412 mov dl,[dataptr] ; Get 2nd part of bitfield from array.
413 push bx ; We need BX so save it.
414 xor bh,bh ; Clear upper byte so we can shift in it.
415 mov bl,ch ; Put mask in BL.
416 shl bx,cl ; Shift mask to proper location.
417 not bx ; Complement it to mask-out the required bitfield.
418 and dx,bx ; Mask-out the required bitfield.
419 pop bx ; Restore pointer.
420 or ax,dx ; Merge the bitfields.
421 mov [dataptr],al ; Store lower byte.
422 inc dataptr ; Adjust pointer.
423 mov [dataptr],ah ; Store upper byte.
424 pop ax ; Restore value.
425 pop cx ; Restore mask and shift-count.
426
427 ; Done.
428 jmp CONV_SetBitfieldValue_end
429
430 CONV_SetBitfieldValue_nospan:
431 ; Merge the bitfield to the array.
432 push cx ; Save mask (CH) and shift-count (CL).
433 push ax ; Save value to store.
434 and al,ch ; Mask value.
435 shl al,cl ; Move the bitfield to the proper location.
436 mov dl,[dataptr] ; Get byte containing bitfield.
437 shl ch,cl ; Shift mask to proper location.
438 not ch ; Complement it to mask-out the required bitfield.
439 and dl,ch ; Mask-out the required bitfield.
440 or al,dl ; Merge the bitfields.
441 mov [dataptr],al ; Store byte containing bitfield.
442 pop ax ; Restore value.
443 pop cx ; Restore mask and shift-count.
444
445 CONV_SetBitfieldValue_end:
446 mov ah,ch ; Get mask in AH.
447 and al,ah ; Mask value.
448 }
449
450 // Epilog code.
451 // Restore caller's DS.
452 _asm {
453 pop ds
454 }
455
456 return value;
457}
458
459
460
461
462
463
464
465
466// ============================================================================
467// Platform-specific helper functions
468// ============================================================================
469
470
471/*
472// Helper functions -- DOS implementation.
473*/
474#ifdef PLATFORM_DOS
475 USHORT CountHarddrives (void) {
476 USHORT NumDrives = 0;
477
478 /* Return the byte at 0040:0075 that contains the nr. of harddisks */
479 _asm {
480 push es ; We use ES to address the 40h segment.
481 mov ax,40h ; Segment address of DOS BIOS DATA.
482 mov es,ax ; Make ES address it.
483 xor ax,ax ; Clear AX to receive return value.
484 mov al,es:[0075h] ; Nr. of harddisks in AL.
485 pop es ; Restore ES.
486 mov [NumDrives],ax ; Return this value.
487 }
488 return NumDrives;
489 }
490
491 /*
492 // On DOS this geometry check uses the INT13X value for sectors per track.
493 // On OS/2 the DosDevIOCtl call uses a SPT value from the formatted disk,
494 // irrespective of the physical geometry.
495 */
496 BOOL HarddriveCheckGeometry (void) {
497 BOOL rv = FALSE;
498
499 _asm {
500 ; According to Ralf Brown ES:DI=0000:0000 to avoid BIOS quirks.
501 push es
502 push di
503 xor di,di
504 mov es,di
505
506 ; Get the disk parameters using normal (non-I13X) access.
507 mov ah,08h ; Get Disk Parameters.
508 mov dl,80h ; Boot Disk.
509 int 13h ; Transfer to BIOS.
510
511 ; Check for errors
512 mov dx,0 ; Assume error.
513 jc end ; CY if error.
514 test ah,ah ; Double check for return-status.
515 jnz end ; AH non-zero if error.
516
517 ; Check sectors per track to be above 62
518 and cl,00111111b ; Mask sectors.
519 cmp cl,SECTOR_COUNT ; Compare with max. AiR-BOOT sectors.
520 jbe end ; SECTOR_COUNT or less is not enough.
521
522 inc dx ; Set to no error.
523
524 end:
525 mov ax,dx ; Status to AX.
526
527 ; Store in return value.
528 mov word ptr [rv],ax
529
530 ; Restore ES:DI
531 pop di
532 pop es
533 }
534 return rv;
535 }
536
537
538
539 BOOL Track0Load (void) {
540 BOOL Success = FALSE;
541
542 _asm {
543
544 push es ; ES is used to point to loadbuffer.
545
546 ; Load the complete AiR-BOOT image from Track0.
547 mov ah,02h ; Read sectors from disk.
548 mov al,SECTOR_COUNT ; Number of sectors to read.
549 mov cx,1 ; Cyl 0, Sector 1.
550 mov dh,0 ; Head 0.
551 mov dl,80h ; Boot Disk.
552 les bx,[Track0] ; Buffer in ES:BX.
553 int 13h ; Transfer to BIOS.
554
555 ; Check for errors
556 mov dx,0 ; Assume error.
557 jc end ; CY if error.
558 test ah,ah ; Double check status in AH.
559 jnz end ; AH non-zero if error.
560
561 inc dx ; Set to no error.
562
563 end:
564 mov ax,dx ; Status to AX.
565
566 ; Store in return value.
567 mov word ptr [Success],ax
568
569 ; Restore ES.
570 pop es
571 }
572
573 return Success;
574 }
575
576 ULONG Track0Write (void) {
577 BOOL Success = FALSE;
578
579 _asm {
580
581 push es ; ES is used to point to savebuffer.
582
583 ; Save the complete AiR-BOOT image to Track0.
584 mov ah,03h ; Write sectors to disk.
585 mov al,SECTOR_COUNT ; Number of sectors to write.
586 mov cx,1 ; Cyl 0, Sector 1.
587 mov dh,0 ; Head 0.
588 mov dl,80h ; Boot Disk.
589 les bx,[Track0] ; Buffer in ES:BX.
590 int 13h ; Transfer to BIOS.
591
592 ; Check for errors
593 mov dx,0 ; Assume error.
594 jc end ; CY if error.
595 test ah,ah ; Double check status in AH.
596 jnz end ; AH non-zero if error.
597
598 inc dx ; Set to no error.
599
600 end:
601 mov ax,dx ; Status to AX.
602
603 ; Store in return value.
604 mov word ptr [Success],ax
605les bx,[Track0]
606mov dx,es
607mov ax,bx
608mov ax,word ptr [Track0]
609mov dx,word ptr [Track0+2]
610 ; Restore ES.
611 pop es
612 }
613
614 //return Success;
615 }
616
617 void RebootSystem (void) {
618 _asm {
619 ; 65 * 65536 = 4259840 us = 4.2 sec.
620 mov ax,8600h ; BIOS Wait.
621 xor dx,dx ; Micro seconds Low.
622 mov cx,65 ; Micro seconds High.
623 int 15h ; Transfer to BIOS.
624
625 //~ ; Try reboot via keyboard.
626 //~ mov al,0feh
627 //~ out 64h,al
628
629 ; Otherwise jump to F000:FFF0.
630 db 0EAh
631 dw 0FFF0h
632 dw 0F000h
633 }
634 return;
635 }
636
637#endif
638
639
640
641/*
642// Helper functions -- OS/2 implementation.
643*/
644#ifdef PLATFORM_OS2
645 USHORT CountHarddrives (void) {
646 USHORT NumDrives = 0;
647 if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &NumDrives, sizeof(NumDrives),NULL, 0) != 0)
648 return 0;
649 return NumDrives;
650 }
651
652 USHORT OS2_GetIOCTLHandle () {
653 USHORT IOCTLHandle = 0;
654 if (DosPhysicalDisk(INFO_GETIOCTLHANDLE, &IOCTLHandle, sizeof(IOCTLHandle),"1:" , 3) != 0)
655 return 0;
656 return IOCTLHandle;
657 }
658
659 void OS2_FreeIOCTLHandle (USHORT IOCTLHandle) {
660 DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &IOCTLHandle, sizeof(IOCTLHandle));
661 return;
662 }
663
664 // Special feature for OS/2, finds out boot drive letter and sends this
665 // information to AiR-BOOT, so that it's able to set that information
666 // during boot phase. Otherwise the user would have to set this.
667 UCHAR AutoDriveLetter = ' ';
668 ULONG AutoDriveLetterSerial = 0;
669
670 void OS2_GetBootAutoDriveLetter (void) {
671 ULONG BootDrive;
672 struct {
673 ULONG ulVSN;
674 VOLUMELABEL vol;
675 } InfoLevel2;
676 DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive));
677 // BootDrive - 1-A:, 2-B:, 3-C:
678 if ((BootDrive>2) & (!DosQueryFSInfo(BootDrive, FSIL_VOLSER, (PVOID)(&InfoLevel2), sizeof(InfoLevel2)))) {
679 AutoDriveLetter = (UCHAR) BootDrive+0x7D;
680 AutoDriveLetterSerial = InfoLevel2.ulVSN;
681 if (!Option_CID) {
682 printf("%X\n", InfoLevel2.ulVSN);
683 }
684 }
685 }
686
687 /*
688 // On DOS this geometry check uses the INT13X value for sectors per track.
689 // On OS/2 the DosDevIOCtl call uses a SPT value from the formatted disk,
690 // irrespective of the physical geometry.
691 */
692 BOOL HarddriveCheckGeometry (void) {
693 USHORT IOCTLHandle;
694 USHORT SectorsPerTrack = 0;
695 DEVICEPARAMETERBLOCK DeviceParmBlock;
696 ULONG ulDataLength;
697
698 IOCTLHandle = OS2_GetIOCTLHandle();
699
700 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS, NULL, 0, NULL, &DeviceParmBlock, sizeof(DeviceParmBlock), &ulDataLength))
701 SectorsPerTrack = DeviceParmBlock.cSectorsPerTrack;
702 OS2_FreeIOCTLHandle (IOCTLHandle);
703 //if (SectorsPerTrack > 61) return TRUE;
704 if (SectorsPerTrack > SECTOR_COUNT) return TRUE;
705 // OS/2 is only able to support 512-byte/sector media, so we dont need to check this
706 return FALSE;
707 }
708
709 BOOL Track0Load (void) {
710 USHORT IOCTLHandle;
711 ULONG TrackLayoutLen = sizeof(TRACKLAYOUT)+sizeof(ULONG)*(SECTOR_COUNT-1);
712 TRACKLAYOUT *TrackLayoutPtr = (TRACKLAYOUT*) malloc(TrackLayoutLen);
713 ULONG cbParms = sizeof(TrackLayoutPtr);
714 ULONG cbData = BYTES_PER_SECTOR;
715 int i;
716 BOOL Success = FALSE;
717
718 IOCTLHandle = OS2_GetIOCTLHandle();
719
720 TrackLayoutPtr->bCommand = 0x01;
721 TrackLayoutPtr->usHead = 0;
722 TrackLayoutPtr->usCylinder = 0;
723 TrackLayoutPtr->usFirstSector = 0;
724 TrackLayoutPtr->cSectors = SECTOR_COUNT;
725
726 for (i=0; i<SECTOR_COUNT; i++) {
727 TrackLayoutPtr->TrackTable[i].usSectorNumber = i+1;
728 TrackLayoutPtr->TrackTable[i].usSectorSize = BYTES_PER_SECTOR;
729 }
730
731 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_READPHYSTRACK,
732 TrackLayoutPtr, cbParms, &cbParms, Track0, cbData, &cbData))
733 Success = TRUE;
734
735 OS2_FreeIOCTLHandle (IOCTLHandle);
736 free (TrackLayoutPtr);
737 return Success;
738 }
739
740 BOOL Track0Write (void) {
741 USHORT IOCTLHandle;
742 ULONG TrackLayoutLen = sizeof(TRACKLAYOUT)+sizeof(ULONG)*(SECTOR_COUNT-1);
743 TRACKLAYOUT *TrackLayoutPtr = (TRACKLAYOUT*) malloc(TrackLayoutLen);
744 ULONG cbParms = sizeof(TrackLayoutPtr);
745 ULONG cbData = BYTES_PER_SECTOR;
746 INT i;
747 BOOL Success = FALSE;
748
749 IOCTLHandle = OS2_GetIOCTLHandle();
750
751
752 TrackLayoutPtr->bCommand = 0x01;
753 TrackLayoutPtr->usHead = 0;
754 TrackLayoutPtr->usCylinder = 0;
755 TrackLayoutPtr->usFirstSector = 0;
756 TrackLayoutPtr->cSectors = SECTOR_COUNT;
757
758 for (i=0; i<SECTOR_COUNT; i++) {
759 TrackLayoutPtr->TrackTable[i].usSectorNumber = i+1;
760 TrackLayoutPtr->TrackTable[i].usSectorSize = BYTES_PER_SECTOR;
761 }
762
763 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_WRITEPHYSTRACK,
764 TrackLayoutPtr, cbParms, &cbParms, Track0, cbData, &cbData))
765 Success = TRUE;
766
767 OS2_FreeIOCTLHandle (IOCTLHandle);
768 free (TrackLayoutPtr);
769 return Success;
770 }
771
772 #define CATEGORY_DOSSYS 0xD5
773 #define FUNCTION_REBOOT 0xAB
774
775 void RebootSystem (void) {
776 HFILE DosHandle;
777 ULONG DosOpenAction;
778
779 DosSleep (2000);
780 if (!DosOpen("DOS$", &DosHandle, &DosOpenAction, 0, FILE_NORMAL, FILE_OPEN, OPEN_ACCESS_READWRITE|OPEN_SHARE_DENYNONE, NULL)) {
781 DosDevIOCtl(DosHandle, CATEGORY_DOSSYS, FUNCTION_REBOOT, NULL, 0, NULL, NULL, 0, NULL);
782 DosSleep (60000);
783 }
784 DosClose(DosHandle);
785 }
786#endif
787
788
789
790
791/*
792// Helper functions -- Win32 implementation.
793*/
794#ifdef PLATFORM_WINNT
795 // Checks, if we are under NT
796 BOOL CheckWindowsVersion (void) {
797 OSVERSIONINFO Version;
798 Version.dwOSVersionInfoSize = sizeof(Version);
799 GetVersionEx(&Version);
800 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
801 return TRUE;
802 if (!Option_CID) {
803 printf(" - This installer is for WindowsNT family only.\n");
804 printf(" Please use DOS installer for Windows9x.\n");
805 }
806 return FALSE;
807 }
808
809
810 HANDLE WINNT_GetIOCTLHandle (void) {
811 return CreateFile("\\\\.\\physicaldrive0", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
812 }
813
814 void WINNT_FreeIOCTLHandle (HANDLE IOCTLHandle) {
815 CloseHandle(IOCTLHandle);
816 }
817
818 USHORT CountHarddrives (void) {
819 return 1;
820 }
821
822 BOOL HarddriveCheckGeometry (void) {
823 HANDLE IOCTLHandle;
824 DISK_GEOMETRY Geometry;
825 USHORT SectorsPerTrack = 0;
826 DWORD Dummy;
827
828 IOCTLHandle = WINNT_GetIOCTLHandle();
829 if (DeviceIoControl(IOCTLHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Geometry, sizeof(Geometry), &Dummy, NULL))
830 SectorsPerTrack = (USHORT) Geometry.SectorsPerTrack;
831 WINNT_FreeIOCTLHandle(IOCTLHandle);
832 //if (SectorsPerTrack > 61) return TRUE; // >60 should also be ok for normal image (60 for image 1 for lvm)
833 if (SectorsPerTrack > SECTOR_COUNT)
834 return TRUE; // Note: This is 1 sector smaller than above !!
835
836 return FALSE;
837 }
838
839 BOOL Track0Load (void) {
840 HANDLE IOCTLHandle;
841 DWORD BytesRead = 0;
842 BOOL Success = FALSE;
843
844 IOCTLHandle = WINNT_GetIOCTLHandle();
845 SetFilePointer(IOCTLHandle, 0, 0, FILE_BEGIN);
846 if (ReadFile(IOCTLHandle, Track0, SECTOR_COUNT * BYTES_PER_SECTOR, &BytesRead, NULL))
847 Success = TRUE;
848 WINNT_FreeIOCTLHandle(IOCTLHandle);
849 return Success;
850 }
851
852 BOOL Track0Write (void) {
853 HANDLE IOCTLHandle;
854 DWORD BytesWritten = 0;
855 BOOL Success = FALSE;
856
857 IOCTLHandle = WINNT_GetIOCTLHandle();
858 SetFilePointer(IOCTLHandle, 0, 0, FILE_BEGIN);
859 if (WriteFile(IOCTLHandle, Track0, SECTOR_COUNT * BYTES_PER_SECTOR, &BytesWritten, NULL))
860 Success = TRUE;
861 WINNT_FreeIOCTLHandle(IOCTLHandle);
862 return Success;
863 }
864
865 void RebootSystem (void) {
866 HANDLE token;
867 TOKEN_PRIVILEGES tokenpriv;
868 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token);
869 LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tokenpriv.Privileges[0].Luid);
870 tokenpriv.PrivilegeCount = 1;
871 tokenpriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
872 AdjustTokenPrivileges(token, FALSE, &tokenpriv, 0, NULL, 0);
873 ExitWindowsEx(EWX_REBOOT, 0);
874 }
875#endif
876
877
878/*
879// Helper functions -- Linux implementation.
880*/
881#ifdef PLATFORM_LINUX
882 USHORT CountHarddrives (void) {
883 USHORT NumDrives = 0;
884 // Implement !
885 return NumDrives;
886 }
887
888 BOOL HarddriveCheckGeometry (void) {
889
890 // Implement !
891 return FALSE;
892 }
893
894 BOOL Track0Load (void) {
895 BOOL Success = FALSE;
896
897 // Implement !
898 return Success;
899 }
900
901 BOOL Track0Write (void) {
902 BOOL Success = FALSE;
903
904 // Implement !
905 return Success;
906 }
907
908 void RebootSystem (void) {
909
910 // Implement !
911 }
912
913#endif
914
915
916
917
918
919// ============================================================================
920// Common Code
921// ============================================================================
922
923
924USHORT GetChecksumOfSector (USHORT Checksum, PCHAR SectorPtr) {
925 PUSHORT TempPtr = (PUSHORT)SectorPtr;
926 USHORT i;
927 for (i=0; i<256; i++) {
928 Checksum = *TempPtr ^ 0xBABE ^ Checksum;
929 TempPtr++;
930 }
931 if (Checksum==0)
932 Checksum = 1;
933 return Checksum;
934}
935
936// Loads airboot.bin into memory (if possible) and sets some variables
937// also makes sure that airboot.bin has correct length
938BOOL LoadBootcodeFromFile (void) {
939 FILE *FileHandle = NULL;
940 ULONG BootcodeSize = 0;
941
942 // Try to open file...
943 FileHandle = fopen(IMAGE_NAME, "rb");
944 if (!FileHandle) {
945 if (!Option_CID) {
946 printf("%s not found\n", IMAGE_NAME);
947 }
948 return FALSE;
949 }
950
951 // Seek to end of file to determine image size...
952 fseek (FileHandle, 0, SEEK_END);
953 BootcodeSize = ftell(FileHandle);
954 if (BootcodeSize!=IMAGE_SIZE && BootcodeSize!=IMAGE_SIZE_60SECS) {
955 fclose (FileHandle);
956 if (!Option_CID) {
957 printf("Invalid %sn\n", IMAGE_NAME);
958 }
959 return FALSE;
960 }
961
962 // Read whole file into memory...
963 fseek (FileHandle, 0, SEEK_SET);
964 fread (Bootcode, 1, IMAGE_SIZE, FileHandle);
965 fclose (FileHandle);
966
967 // Extract language and version info...
968 Bootcode_Version = (Bootcode[13] << 8) | Bootcode[14];
969 Bootcode_LanguageID = Bootcode[15];
970 Bootcode_ConfigVersion = (Bootcode[0x6C0D] << 8) | Bootcode[0x6C0E];
971 return TRUE;
972}
973
974/**
975 * Check MBR and AB signatures.
976 * Also check code sectors if AB is installed.
977 * Set global status accordingly.
978 */
979void Status_CheckCode (void) {
980 USHORT TotalCodeSectorsUsed = 0;
981 USHORT Checksum = 0;
982 PCHAR SectorPtr = NULL;
983
984 if (Status_Code==STATUS_IMPOSSIBLE)
985 return;
986 // EZ-Setup check!
987 Status_Code = STATUS_NOTINSTALLED;
988 if ((Track0[0x1FE]!=0x55) || (Track0[0x1FF]!=0xAA))
989 return; // No MBR signature found, so not installed
990 if (strncmp(&Track0[2], "AiRBOOT", 7)!=0)
991 return; // No AiR-BOOT signature found, so not installed
992 // MBR and AiR-BOOT signature found...
993 TotalCodeSectorsUsed = Track0[0x10]; // 34h/52 in v1.06
994 SectorPtr = &Track0[1 * BYTES_PER_SECTOR]; // Start at sector 2
995 // Calculate checksum of code-sectors
996 while (TotalCodeSectorsUsed>0) {
997 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
998 SectorPtr += BYTES_PER_SECTOR;
999 TotalCodeSectorsUsed--;
1000 }
1001 if (Checksum!=*(PUSHORT)&Track0[0x11]) {
1002 Status_Code = STATUS_CORRUPT;
1003 return; // Bad checksum for code
1004 }
1005 // Checksum fine...
1006 Installed_LanguageID = Track0[0x0F];
1007 Installed_CodeVersion = (Track0[0x0D] << 8) | Track0[0x0E];
1008 if (Installed_CodeVersion<Bootcode_Version)
1009 Status_Code = STATUS_INSTALLEDMGU; // Do upgrade
1010 else
1011 Status_Code = STATUS_INSTALLED; // Same version installed
1012
1013 return;
1014}
1015
1016
1017void Status_CheckConfig (void) {
1018 PCHAR ConfigSectorPtr = &Track0[CONFIG_OFFSET]; // Config sector offset hard-coded !
1019 PCHAR SectorPtr = NULL;
1020 USHORT Checksum = 0;
1021 USHORT ConfigChecksum = 0;
1022 USHORT SectorCount = 0;
1023
1024 /*
1025 // Note that the 'AiRCFG-TABLE' string includes the invisible 0xAD char.
1026 */
1027 if (strncmp(ConfigSectorPtr, "AiRCFG-TABLE­", 13)==0) {
1028 // AiR-BOOT signature found...
1029 SectorPtr = &Track0[54 * BYTES_PER_SECTOR]; // Start at sector 55
1030 ConfigChecksum = *(PUSHORT)&Track0[54 * BYTES_PER_SECTOR + 20];
1031 // Remove checksum
1032 *(PUSHORT)&Track0[54 * BYTES_PER_SECTOR + 20] = 0; // Config sector secnum hard-coded !
1033
1034 /*
1035 // Rousseau: # Keep compatible with v1.07 CRC #
1036 // AB v1.07 had bugs in writing the wrong number of AB config sectors.
1037 // This is fixed in v1.0.8 but the CRC has to be calculated the "v1.07 way"
1038 // otherwise v1.07 SET(A)BOOT and INSTALL2.EXE will think the AB config
1039 // is corrupted.
1040 // So the CRC is calculated over 5 sectors instead of 7.
1041 */
1042 SectorCount = 5;
1043
1044 while (SectorCount>0) {
1045 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1046 SectorPtr += BYTES_PER_SECTOR;
1047 SectorCount--;
1048 }
1049 // Restore checksum
1050 *(PUSHORT)&Track0[54 * BYTES_PER_SECTOR + 20] = ConfigChecksum; // Config sector secnum hard-coded !
1051 if (Checksum!=ConfigChecksum) {
1052 Status_Config = STATUS_CORRUPT;
1053 return;
1054 }
1055 // Checksum fine
1056 Installed_ConfigVersion = (Track0[54 * BYTES_PER_SECTOR + 0x0D] << 8) | Track0[54 * BYTES_PER_SECTOR + 0x0E];
1057 if (Installed_ConfigVersion>=Bootcode_ConfigVersion) {
1058 Status_Config = STATUS_INSTALLED;
1059 return;
1060 }
1061 Status_Config = STATUS_INSTALLEDMGU;
1062 // Those upgrades will copy useful configuration data to the image config
1063 // If new configuration data was added, those spaces are not overwritten
1064 // Sector 60 (MBR-BackUp) *MUST BE* copied, otherwise it would be lost.
1065 // Rousseau: Upgrade from v0.27
1066 if (Installed_ConfigVersion<=0x27) {
1067 // UPGRADE v0.27 and prior versions
1068
1069 // Sector 55
1070 // Changes: Offset 69 length 75 - Linux command line
1071 // Offset 144 length 1 - Linux kernel partition
1072 // Offset 145 Length 11 - Default kernel name
1073 // Offset 156 Length 1 - Kernel name terminator 1
1074 // Offset 157 Length 11 - Last kernel name
1075 // Offset 168 Length 1 - Kernel name terminator 2
1076 // Offset 169 Length 1 - Ext. partition M$-hack enable
1077 // -> Total-length 101
1078 // Offset 432 Length 34 - New IPT entry (BIOS continued)
1079 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], 69 - 16); // CHECKEN !!
1080 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 466], &Track0[54 * BYTES_PER_SECTOR + 466], 46); // CHECKEN !!
1081 // Sector 56-57 no changes
1082 memcpy(&Bootcode[55*512], &Track0[55 * BYTES_PER_SECTOR], 1024);
1083 // Sector 58-59
1084 // Changes: Offset 900 Length 30 - Logical driveletter table
1085 memcpy(&Bootcode[57 * BYTES_PER_SECTOR], &Track0[57 * BYTES_PER_SECTOR], 900); // AANPASSEN 900 !!
1086 // Sector 60 copy unmodified
1087 memcpy(&Bootcode[59 * BYTES_PER_SECTOR], &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // CHECKEN !!
1088 return;
1089 }
1090 // Rousseau: Upgrade from v0.91
1091 if (Installed_ConfigVersion<=0x91) {
1092 // UPGRADE v0.91 and prior versions
1093 // Sector 55-57 no changes
1094 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR + 1024 - 16); // CHACKEN !!
1095 // Sector 58-59
1096 // Changes: Offset 900 Length 30 - Logical driveletter table
1097 memcpy(&Bootcode[57 * BYTES_PER_SECTOR], &Track0[57 * BYTES_PER_SECTOR], 900); // AANPASSEN 900 !!
1098 // Sector 60/62 copy unmodified
1099 memcpy(&Bootcode[59 * BYTES_PER_SECTOR], &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR);
1100 return;
1101 }
1102
1103
1104 // UPGRADE to v1.06 format.
1105 // We don't need to "upgrade" the configuration to move to v1.06, we simply copy it over.
1106 // From Sector 55, 6 sectors in total but never header/version.
1107 // Rousseau: We copy two more sectors (8 in total) in the extended (45 partition) version.
1108 switch (IMAGE_SIZE) {
1109 case IMAGE_SIZE_60SECS: {
1110 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR * 6 - 16);
1111 break;
1112 }
1113 case IMAGE_SIZE_62SECS: {
1114 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR * 8 - 16);
1115 break;
1116 }
1117 }
1118
1119 /*
1120 // Convert v1.06 hideparttable (30x30) to the v1.07 (30x45) format.
1121 */
1122 if ((Installed_ConfigVersion == 0x102) && (Bootcode_ConfigVersion >= 0x107)) {
1123 int i,j;
1124 char c;
1125 //printf("Converting 1.06 -> 1.07 hidepart");
1126 memcpy(&Bootcode[0x7400], &Track0[0x7200], 900);
1127 memset(TempHidPartTable, 0xff, 45 * 34);
1128 for (i=0; i<30; i++) {
1129 for (j=0; j<30; j++) {
1130 c = Bootcode[0x7400+i*30+j];
1131 TempHidPartTable[i*45+j] = c;
1132 }
1133 }
1134 memcpy(&Bootcode[0x7400], TempHidPartTable, 30 * 45);
1135 }
1136
1137 /*
1138 // Convert v1.07 hideparttable (30x45) to a packed v1.0.8+ (45x45) format.
1139 */
1140 if ((Installed_ConfigVersion < 0x108) && (Bootcode_ConfigVersion >= 0x108)) {
1141 int i,j;
1142 char c;
1143 //printf("Converting to 1.08 packed hidepart");
1144 memset(TempHidPartTable, 0xff, 45 * 34);
1145 // Unpacked table is 30 rows with 45 columns per row.
1146 // Packed table is 45 rows with 45 columns per row packed in 34 bytes.
1147 for (i=0; i<30; i++) {
1148 for (j=0; j<45; j++) {
1149 c = Bootcode[0x7400+i*45+j]; // Get unpacked value
1150 c = set_bitfield(&TempHidPartTable[i*34], j, 6, c); // Store 6-bit packed value
1151 }
1152 }
1153 memcpy(&Bootcode[0x7400], TempHidPartTable, 45 * 34);
1154 }
1155
1156 return;
1157 }
1158 // MKW:
1159 // Check for prior v0.26 signature
1160 // not supported in C version anymore
1161 // Don't have this version here for testing and I can't risk breaking
1162 // configuration
1163 return;
1164}
1165
1166// Checks partition table for valid data
1167BOOL Virus_CheckThisMBR (PCHAR MBRptr) { // Rousseau: adjusted this function
1168 USHORT PartitionNo;
1169 ////ULONG CHSStart, CHSEnd;
1170
1171 //printf("DEBUG: Virus_CheckThisMBR\n");
1172
1173 if (*(PUSHORT)(MBRptr + BYTES_PER_SECTOR - 2)!=0x0AA55)
1174 return FALSE;
1175
1176 //printf("DEBUG: Virus_CheckThisMBR - Checking Partitions\n");
1177
1178 MBRptr += 446;
1179 for (PartitionNo=0; PartitionNo<4; PartitionNo++) {
1180 if (*(MBRptr+4) != 0) {
1181 /*
1182 // Rousseau 2011-02-04: ## Check for GPT ##
1183 */
1184 if (*(MBRptr+4) == GPT) {
1185 if (!Option_CID) {
1186 printf("ERROR: This drive is partitioned with the modern GPT layout.\n");
1187 printf(" AiR-BOOT is currently unable to handle GPT partitioned drives.\n");
1188 printf(" Installation aborted, no changes made.\n");
1189 }
1190 exit(2);
1191 }
1192
1193 /*
1194 // Rousseau: 2011-05-05
1195 // Last minute change to have AB install on a disk
1196 // with nopartitions on the it. (check !)
1197 // It still checks for GPT but will skip the check below.
1198 */
1199 continue;
1200
1201 //printf("DEBUG: Virus_CheckThisMBR - Partition: %d\n", PartitionNo);
1202 // Partition-type defined, analyse partition data
1203 ////CHSStart = (*(MBRptr+3) | ((*(MBRptr+2) >> 6) << 8)) << 16; // Cylinder
1204 ////CHSStart |= (*(MBRptr+2) & 0x3F) | ((*(MBRptr+1) << 8)); // Sector / Head
1205 //printf("DEBUG: Virus_CheckThisMBR - CHSStart: %d\n", CHSStart); // 3F MASK CHECKEN !!
1206
1207 ////CHSEnd = (*(MBRptr+7) | ((*(MBRptr+6) >> 6) << 8)) << 16; // Cylinder
1208 ////CHSEnd |= (*(MBRptr+6) & 0x3F) | ((*(MBRptr+5) << 8)); // Sector / Head
1209 //printf("DEBUG: Virus_CheckThisMBR - CHSEnd: %d\n", CHSEnd);
1210
1211
1212 /*
1213 // Rousseau 2011-02-03: ## Changed below from < to <= ##
1214 // When a partition is above 1024x255x63 (8GiB) the start and end of the partition
1215 // in the MBR is the same (1024/255/63) to indicate extended CHS-values.
1216 // This made the installer see this as a non-valid entry.
1217 // Fixme: This could use some further optimazation like checking if CHS is really 1024/255/63
1218 // to exclude truly faulty partition-entries.
1219 // Also depends on conventions: IBM,MS,Partition Magic,...
1220 */
1221 /*if (CHSStart<CHSEnd) {*/
1222 ////if (CHSStart<=CHSEnd) {
1223 //// if (*(PULONG)(MBRptr+12)!=0) // Absolute length > 0?
1224 //// return TRUE;
1225 ////}
1226 }
1227 // Go to next partition
1228 MBRptr += 16;
1229 }
1230 // No partitions defined/no valid partitions found
1231 // Rousseau: Still return TRUE (OK)
1232 //return FALSE;
1233 return TRUE;
1234}
1235
1236BOOL Virus_CheckCurrentMBR (void) {
1237 return Virus_CheckThisMBR((PCHAR) Track0);
1238}
1239
1240BOOL Virus_CheckForBackUpMBR (void) {
1241 BOOL bMbrBackup = FALSE;
1242
1243 // All versions above v1.06 have expanded tables so the MBR-backup
1244 // is located 2 sectors higher in the track0 image.
1245 if (Installed_ConfigVersion<=0x0106)
1246 bMbrBackup = Virus_CheckThisMBR((PCHAR) &Track0[59 * BYTES_PER_SECTOR]);
1247 else
1248 bMbrBackup = Virus_CheckThisMBR((PCHAR) &Track0[61 * BYTES_PER_SECTOR]);
1249
1250 return bMbrBackup;
1251}
1252
1253BOOL Virus_CheckForStealth (void) {
1254 PCHAR CurPtr = (PCHAR) Track0;
1255 USHORT i;
1256
1257 for (i=0; i<511; i++) {
1258 if (*(PUSHORT)CurPtr==0x13CD) return FALSE;
1259 CurPtr++;
1260 }
1261 // No CD13h found? possible stealth
1262 return TRUE;
1263}
1264
1265// Copies backup MBR into current MBR on current memory copy of track 0
1266// Rousseau: Two sectors higher in the extended version.
1267void Virus_CopyBackUpMBR (void) {
1268 switch (IMAGE_SIZE) {
1269 case IMAGE_SIZE_60SECS: {
1270 memcpy(Track0, &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // sector 60
1271 break;
1272 }
1273 case IMAGE_SIZE_62SECS: {
1274 memcpy(Track0, &Track0[61 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // sector 62
1275 break;
1276 }
1277 }
1278}
1279
1280void Status_PrintF (ULONG Status, USHORT Version) {
1281 switch (Status) {
1282 case STATUS_NOTINSTALLED: {
1283 if (!Option_CID) {
1284 printf("not installed\n");
1285 }
1286 break;
1287 }
1288 case STATUS_CORRUPT: {
1289 if (!Option_CID) {
1290 printf("not intact\n");
1291 }
1292 break;
1293 }
1294 case STATUS_INSTALLED:
1295 case STATUS_INSTALLEDMGU:
1296 if (!Option_CID) {
1297 printf("intact (v%x.%1d.%1d)", Version>>8, (Version & 0x0F0)>>4, Version & 0x0F);
1298 }
1299 if (Status==STATUS_INSTALLEDMGU)
1300 if (!Option_CID) {
1301 printf(", but may be updated");
1302 }
1303 if (!Option_CID) {
1304 printf("\n");
1305 }
1306 break;
1307
1308 case STATUS_IMPOSSIBLE:
1309 if (!Option_CID) {
1310 printf(ImpossibleCause);
1311 }
1312 break;
1313 }
1314}
1315
1316void Language_PrintF(UCHAR LanguageID) {
1317 if (Option_CID)
1318 return;
1319 switch (LanguageID) {
1320 case 'E': printf("english"); break;
1321 case 'N': printf("dutch"); break; // Changed from 'D' to 'N'
1322 case 'G': printf("german"); break;
1323 case 'F': printf("french"); break;
1324 case 'I': printf("italian"); break;
1325 case 'R': printf("russian"); break;
1326 case 'S': printf("swedish"); break;
1327 default: printf("unknown");
1328 }
1329}
1330
1331// Doesn't actually write code/config, but writes it to track0 memory
1332void Install_WriteCode (void) {
1333 USHORT TotalCodeSectorsUsed = 0;
1334 USHORT SectorCount = 0;
1335 USHORT Checksum = 0;
1336 PCHAR SectorPtr = NULL;
1337
1338 // Calculate checksum for code...
1339 TotalCodeSectorsUsed = Bootcode[0x10]; // SECTORS USED CHECKEN !! (34h / 52d in v1.06)
1340 SectorPtr = &Bootcode[1 * BYTES_PER_SECTOR]; // Start at sector 2
1341 SectorCount = TotalCodeSectorsUsed;
1342 while (SectorCount>0) {
1343 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1344 SectorPtr += BYTES_PER_SECTOR;
1345 SectorCount--;
1346 }
1347 *(PUSHORT)&Bootcode[0x11] = Checksum;
1348
1349 // Copy MBR till offset 0x1B8 (Windows NT hdd signature location)
1350 memcpy(Track0, Bootcode, 0x1B8);
1351
1352 // Copy over code sectors...
1353 memcpy(&Track0[BYTES_PER_SECTOR], &Bootcode[BYTES_PER_SECTOR], TotalCodeSectorsUsed * BYTES_PER_SECTOR);
1354}
1355
1356void Install_WriteConfig (void) {
1357 USHORT SectorCount = 0;
1358 USHORT Checksum = 0;
1359 PCHAR SectorPtr = NULL;
1360
1361#ifdef PLATFORM_OS2
1362 if (AutoDriveLetter!=0) {
1363 // Add DriveLetter Automatic veriables, if set
1364 Bootcode[54 * BYTES_PER_SECTOR + 0x1AB] = AutoDriveLetter; // CHECKEN !
1365 *(PULONG)&Bootcode[54 * BYTES_PER_SECTOR + 0x1AC] = AutoDriveLetterSerial;
1366 }
1367#endif
1368
1369 // Delete current checksum
1370 *(PUSHORT)&Bootcode[54 * BYTES_PER_SECTOR + 20] = 0;
1371
1372 SectorPtr = &Bootcode[54 * BYTES_PER_SECTOR]; // Start at sector 55
1373
1374 /*
1375 // Rousseau: # Keep compatible with v1.07 CRC #
1376 // AB v1.07 had bugs in writing the wrong number of AB config sectors.
1377 // This is fixed in v1.0.8 but the CRC has to be calculated the "v1.07 way"
1378 // otherwise v1.07 SET(A)BOOT and AIRBOOT2.EXE will think the AB config
1379 // is corrupted.
1380 // So the CRC is calculated over 5 sectors instead of 7.
1381 */
1382 SectorCount = 5;
1383
1384 while (SectorCount>0) {
1385 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1386 SectorPtr += BYTES_PER_SECTOR;
1387 SectorCount--;
1388 }
1389 *(PUSHORT)&Bootcode[54 * BYTES_PER_SECTOR + 20] = Checksum;
1390
1391 // Copy configuration sectors
1392 // Rousseau: Two more sectors for extended version.
1393 switch (IMAGE_SIZE) {
1394 case IMAGE_SIZE_60SECS: {
1395 memcpy(&Track0[54 * BYTES_PER_SECTOR], &Bootcode[54 * BYTES_PER_SECTOR], 6 * BYTES_PER_SECTOR);
1396 break;
1397 }
1398 case IMAGE_SIZE_62SECS: {
1399 memcpy(&Track0[54 * BYTES_PER_SECTOR], &Bootcode[54 * BYTES_PER_SECTOR], 8 * BYTES_PER_SECTOR);
1400 break;
1401 }
1402 }
1403
1404 return;
1405}
1406
1407
1408void DumpTrack0() {
1409 int i,j;
1410 for (i=27; i<32; i++) {
1411 for (j=0; j<16; j++) {
1412 printf("%02X",Track0[i*16+j]);
1413 }
1414 printf("\n");
1415 }
1416}
1417
1418
1419
1420
1421void DoDebug() {
1422 USHORT t0codv = 0;
1423 USHORT t0cfgv = 0;
1424 USHORT bccodv = 0;
1425 USHORT bccfgv = 0;
1426
1427 //do_bf_test();
1428
1429 printf("\nHardisks : %d\n", CountHarddrives());
1430 printf("\nGEO : %d\n", HarddriveCheckGeometry());
1431 printf("\nTrack0 : %d\n", Track0Load());
1432 printf("\nBootcode : %d\n", LoadBootcodeFromFile());
1433
1434
1435 // Dump Track0
1436 DumpTrack0();
1437 printf("\n\n");
1438 // Dump Bootcode
1439 //~ {
1440 //~ int i;
1441 //~ for (i=0; i<512; i++) {
1442 //~ printf("%02X",Bootcode[i]);
1443 //~ }
1444 //~ }
1445 //~ printf("\n\n");
1446
1447 t0codv = Track0[13] << 8 | Track0[14];
1448 printf("t0codv : %04X\n", t0codv);
1449
1450 t0cfgv = Track0[0x6c00+13] << 8 | Track0[0x6c00+14];
1451 printf("t0cfgv : %04X\n", t0cfgv);
1452
1453 bccodv = Bootcode[13] << 8 | Bootcode[14];
1454 printf("bccodv : %04X\n", bccodv);
1455
1456 bccfgv = Bootcode[0x6c00+13] << 8 | Bootcode[0x6c00+14];
1457 printf("bccfgv : %04X\n", bccfgv);
1458
1459 return;
1460
1461}
1462
1463
1464// ============================================================================
1465// Main Entrypoint
1466// ============================================================================
1467
1468
1469
1470#define MAXCMDPARMLEN 11
1471
1472int main (int argc, char **argv) {
1473 ULONG CurArgument = 0;
1474 size_t ArgumentLen = 0;
1475 PCHAR StartPos = 0;
1476 UCHAR UserKey = ' ';
1477 BOOL ExitOnly = FALSE;
1478 CHAR TempSpace[MAXCMDPARMLEN+1];
1479
1480
1481 // Check commandline parameters
1482 CurArgument = 1;
1483 while (CurArgument<argc) {
1484 StartPos = argv[CurArgument];
1485 ArgumentLen = strlen(StartPos);
1486
1487 if (((*StartPos=='-') || (*StartPos=='/')) && (ArgumentLen>1)) {
1488 StartPos++; ArgumentLen--;
1489 if (ArgumentLen>MAXCMDPARMLEN)
1490 ArgumentLen = MAXCMDPARMLEN;
1491 strncpy((char *) TempSpace, StartPos, ArgumentLen);
1492 TempSpace[ArgumentLen] = 0;
1493 StartPos = (PCHAR) TempSpace;
1494 while (*StartPos!=0) {
1495 *StartPos = tolower(*StartPos); StartPos++;
1496 }
1497 if (strcmp((char *) TempSpace, "forcecode")==0) Option_ForceCode = TRUE;
1498 if (strcmp((char *) TempSpace, "forceconfig")==0) Option_ForceConfig = TRUE;
1499 if (strcmp((char *) TempSpace, "silent")==0) Option_Silent = TRUE;
1500 if (strcmp((char *) TempSpace, "cid")==0) Option_CID = TRUE;
1501 }
1502 CurArgument++;
1503 }
1504
1505printf("1> c:%d, s:%d\n", Option_CID, Option_Silent);
1506
1507 if (Option_CID) {
1508 Option_Silent = TRUE;
1509 }
1510
1511printf("2> c:%d, s:%d\n", Option_CID, Option_Silent);
1512
1513//exit(1);
1514
1515
1516 // Show header.
1517 if (!Option_CID) {
1518 printf("AiR-BOOT Installer v%s.%s.%s for %s\n",
1519 BLDLVL_MAJOR_VERSION,
1520 BLDLVL_MIDDLE_VERSION,
1521 BLDLVL_MINOR_VERSION,
1522 PLATFORM_NAME);
1523 printf(" - (c) Copyright 1998-2012 by Martin Kiewitz.\n");
1524 printf("\n-> ...Please wait... <-\n");
1525 }
1526
1527
1528 // Allocate buffers for Track0 and AIRBOOT.BIN.
1529 Track0 = malloc(SECTOR_COUNT * BYTES_PER_SECTOR);
1530 Bootcode = malloc(SECTOR_COUNT * BYTES_PER_SECTOR);
1531
1532 printf("TRACK0 : %08lX\n", Track0);
1533 printf("BOOTCODE : %08lX\n", Bootcode);
1534
1535
1536 // Exit of allocation failed.
1537 if (!(Track0 && Bootcode)) {
1538 if (!Option_CID) {
1539 printf("- Unable to allocate enough memory, operation aborted!\n");
1540 }
1541 exit(4);
1542 }
1543
1544
1545 //~ DoDebug();
1546 //~ exit(0);
1547
1548
1549printf("3> c:%d, s:%d\n", Option_CID, Option_Silent);
1550
1551
1552#ifdef PLATFORM_WINNT
1553 if (CheckWindowsVersion()==FALSE)
1554 return 1;
1555#endif
1556
1557 if (CountHarddrives()==0) {
1558 if (!Option_CID) {
1559 printf(" - No physical drives found on this system. Install impossible.\n");
1560 }
1561 return 3; // Rouseau: changed from 1 to 3
1562 }
1563printf("4> c:%d, s:%d\n", Option_CID, Option_Silent);
1564 if (!Option_CID) {
1565 printf(" - Loading bootcode from file...");
1566 }
1567
1568 if (LoadBootcodeFromFile()==FALSE)
1569 return 1;
1570
1571 if (!Option_CID) {
1572 printf("ok\n");
1573 }
1574
1575 if (!Option_CID) {
1576 printf(" - Loading MBR from harddisc...");
1577 }
1578printf("5> c:%d, s:%d\n", Option_CID, Option_Silent);
1579//~ DumpTrack0();
1580 if (!Track0Load()) {
1581 if (!Option_CID) {
1582 printf("LOAD ERROR!\n");
1583 }
1584 return 1;
1585 }
1586 else {
1587 if (!Option_CID) {
1588 printf("ok\n");
1589 }
1590 }
1591//~ DumpTrack0();
1592 if (!HarddriveCheckGeometry()) {
1593 // No EZ-SETUP check here, because we are under 32-bit OS and this
1594 // wouldn't make any sense
1595 //printf("\nDEBUG: STATUS_IMPOSSIBLE\n");
1596 Status_Code = STATUS_IMPOSSIBLE;
1597 ImpossibleCause = "unable to install\n Your harddisc does not have at least 63 sectors per track.";
1598 }
1599
1600
1601 if (!Option_CID) {
1602 printf("\n-> ...Current Status... <-\n");
1603 }
1604
1605 Status_CheckCode();
1606 if (!Option_CID) {
1607 printf(" - AiR-BOOT is ");
1608 }
1609 Status_PrintF(Status_Code, Installed_CodeVersion);
1610 if (Status_Code==STATUS_IMPOSSIBLE)
1611 return 1;
1612 Status_CheckConfig();
1613 if (!Option_CID) {
1614 printf(" - Configuration is ");
1615 }
1616 Status_PrintF(Status_Config, Installed_ConfigVersion);
1617 // Display language as well, if code installed
1618 if ((Status_Code==STATUS_INSTALLED) || (Status_Code==STATUS_INSTALLEDMGU)) {
1619 if (!Option_CID) {
1620 printf(" - Language is ");
1621 }
1622 Language_PrintF(Installed_LanguageID);
1623 if (!Option_CID) {
1624 printf("\n");
1625 }
1626 }
1627printf("6> c:%d, s:%d\n", Option_CID, Option_Silent);
1628 // =============================================================
1629 // PRE-CHECKING, WHAT WE ARE SUPPOSED TO DO...
1630 // =============================================================
1631 if ((Option_ForceCode) || (Status_Code!=STATUS_INSTALLED) || (Installed_LanguageID!=Bootcode_LanguageID))
1632 Install_Code = TRUE; // If LanguageID different or not installed
1633 if ((Option_ForceConfig) || (Status_Config!=STATUS_INSTALLED))
1634 Install_Config = TRUE; // If not installed
1635
1636 if ((Status_Code==STATUS_CORRUPT) || (Status_Config==STATUS_CORRUPT))
1637 Install_IsCorrupt = TRUE; // If anything is corrupt
1638
1639 // =============================================================
1640 // VIRUS
1641 // =============================================================
1642 // If-Table
1643 // ---------
1644 // Code==not installed, Config=not installed -> Check MBR
1645 // Code==installed, config==installed -> Check MBR (-> Virus?)
1646 // Code==not installed, config==installed -> (-> Virus?)
1647 // Code==installed, config==not installed -> Check MBR (-> Virus?)
1648
1649 //printf("DEBUG: Status_Code: %d, Status_Config: %d\n", Status_Code, Status_Config); // Rousseau: DEBUG
1650
1651 if ((Status_Code==STATUS_NOTINSTALLED) & (Status_Config==STATUS_NOTINSTALLED)) {
1652 // Nothing installed, so check MBR, if squashed...
1653 if (!Virus_CheckCurrentMBR()) {
1654 if (!Option_CID) {
1655 printf("\n\n");
1656 printf("AiR-BOOT detected that the data on your harddisc got damaged.\n");
1657 printf("If you had AiR-BOOT installed before: the corruption killed AiR-BOOT completly!\n");
1658 printf("Installation halted.\n");
1659 }
1660 return 255; // Rousseau: changed from 1 to 255
1661 }
1662 //printf("DEBUG: Installing...\n"); // Rousseau: DEBUG
1663 }
1664 else {
1665 if ((Status_Code==STATUS_NOTINSTALLED) | (!Virus_CheckCurrentMBR())) {
1666 // Code not installed, but Config or MBR squashed...
1667 // -> Virus proposed, check for backup (if available)
1668 if (!Option_CID) {
1669 printf("\n\n");
1670 printf("-> ...!ATTENTION!... <-\n");
1671 }
1672 if (Virus_CheckForStealth())
1673 if (!Option_CID) {
1674 printf("Your system GOT infected by a stealth-virus (or your MBR got trashed).\n");
1675 }
1676 else
1677 if (!Option_CID) {
1678 printf("Probably your system was infected by a virus.\n");
1679 printf("Repairing AiR-BOOT will normally squash the virus.\n");
1680 printf("But to be sure it's gone, you should check your harddisc using a virus-scanner.\n");
1681 }
1682
1683 if (!Virus_CheckCurrentMBR()) {
1684 // MBR squashed, so check backup and display message
1685 if (!Option_CID) {
1686 printf("\n");
1687 printf("AiR-BOOT detected that the virus has broken your partition-table.\n");
1688 }
1689 if (Virus_CheckForBackUpMBR()) {
1690 if (!Option_CID) {
1691 printf("Good news: AiR-BOOT has found a (hopefully) functional backup.\n");
1692 printf("Shall I use this backup, instead of the current active one? (Y/N)\n");
1693 }
1694 // User selection, Y/N, if he wants to restore MBR
1695 // *NOT* CID (silent) able
1696 do {
1697 UserKey = getch() | 0x20;
1698 } while (!((UserKey=='y') | (UserKey=='n')));
1699 if (UserKey=='y')
1700 Virus_CopyBackUpMBR();
1701 }
1702 else {
1703 if (!Option_CID) {
1704 printf("Sadly the virus also broke AiR-BOOT's backup. You will have to help yourself.\n");
1705 }
1706 }
1707 }
1708 }
1709 }
1710
1711printf("7> c:%d, s:%d\n", Option_CID, Option_Silent);
1712
1713 // =============================================================
1714 // MAIN-MENU
1715 // =============================================================
1716 if (!Option_CID) {
1717 printf("\n-> ...Please press... <-\n");
1718 }
1719
1720 if (!Option_CID) {
1721 if (Install_IsCorrupt)
1722 printf(" <R> - Repair AiR-BOOT ");
1723 else
1724 if (Status_Code==STATUS_NOTINSTALLED)
1725 printf(" <A> - Add AiR-BOOT ");
1726 else
1727 printf(" <U> - Update/Change AiR-BOOT to ");
1728
1729 printf("'v%x.%1d.%1d/", Bootcode_Version>>8, (Bootcode_Version & 0x0F0)>>4, Bootcode_Version & 0x0F);
1730 Language_PrintF(Bootcode_LanguageID);
1731 printf("' on current system\n");
1732
1733 printf(" <D> - Delete AiR-BOOT from current system\n");
1734 printf(" <Q> - Quit without any change\n");
1735 }
1736
1737
1738printf("8> c:%d, s:%d\n", Option_CID, Option_Silent);
1739
1740 if (Option_Silent || Option_CID) {
1741 // Silent operation? Always add AiR-BOOT then
1742 UserKey = 'a';
1743 }
1744 else {
1745 do {
1746 UserKey = getch() | 0x20;
1747 } while (!((UserKey=='a') || (UserKey=='r') || (UserKey=='u') || (UserKey=='d') || (UserKey=='q')));
1748 }
1749
1750 if (!Option_CID) {
1751 printf("\n\n\n-------------------------------------------------------------------------------\n");
1752 }
1753
1754 switch (UserKey) {
1755 case 'a':
1756 case 'r':
1757 case 'u': {
1758 if (Install_Code || Install_Config) {
1759 if (!Option_CID) {
1760 printf("Add/Repair/Update AiR-BOOT in progress...\n");
1761 }
1762#ifdef PLATFORM_OS2
1763 OS2_GetBootAutoDriveLetter();
1764#endif
1765 if (Install_Code) {
1766 if (!Option_CID) {
1767 printf(" þ Writing AiR-BOOT code...");
1768 }
1769 //~ DumpTrack0();
1770 Install_WriteCode();
1771 //~ DumpTrack0();
1772 if (!Option_CID) {
1773 printf("ok\n");
1774 }
1775 }
1776 if (Install_Config) {
1777 if (!Option_CID) {
1778 printf(" þ Writing AiR-BOOT configuration...");
1779 }
1780 Install_WriteConfig();
1781 if (!Option_CID) {
1782 printf("ok\n");
1783 }
1784 }
1785 //printf("1\n");
1786 //DumpTrack0();
1787 {
1788 ULONG rv;
1789 if (!(rv=Track0Write())) {
1790 //~ if (!Option_CID) {
1791 printf("SAVE ERROR!\n");
1792 //~ }
1793 return 1;
1794 }
1795 printf("\n\n\nRV : %08lX\n\n",(ULONG)rv);
1796 printf("TRACK0 : %08lX\n", Track0);
1797 printf("BOOTCODE : %08lX\n", Bootcode);
1798 }
1799 //printf("2\n");
1800 //DumpTrack0();
1801 if (!Option_CID) {
1802 printf("\n");
1803 printf("Your copy of AiR-BOOT is now fully functional.\n");
1804 if (!Option_Silent) {
1805 printf("Please hit ESC to exit AiR-BOOT installer or ENTER to reboot your system...\n");
1806 }
1807 }
1808 if (Option_Silent || Option_CID) {
1809 // Silent operation? Always reboot system (shall we do this really?)
1810 // No, otherwise installing from MiniLVM will reboot the system
1811 // which is not what the user would expect.
1812 //UserKey = 0x0D;
1813 UserKey = 0x1B;
1814 }
1815 else {
1816 do {
1817 UserKey = getch(); // React on ENTER or ESC
1818 } while (!((UserKey==0x0D) || (UserKey==0x1B)));
1819 }
1820 if (UserKey==0x0D) { // ENTER reboots system... (if not in eCS install mode)
1821
1822 /*
1823 // Rousseau: ## Disable Reboot when installing eComStation ##
1824 // In the install-environment, the MEMDRIVE env-var is defined.
1825 // So, only reboot if this env-var is not defined.
1826 */
1827 if (!getenv("MEMDRIVE")) {
1828 if (!Option_CID) {
1829 printf("Now rebooting system...\n");
1830 }
1831 RebootSystem();
1832 }
1833 ExitOnly = TRUE;
1834 }
1835 }
1836 else {
1837 if (!Option_CID) {
1838 printf(" þ All components of AiR-BOOT are intact and up-to-date. Nothing to do.\n");
1839 }
1840 ExitOnly = TRUE;
1841 }
1842 break;
1843 }
1844 case 'd': {
1845 if (!Option_CID) {
1846 printf(" þ Removing AiR-BOOT automatically is not possible at this time.\n");
1847 }
1848#ifdef PLATFORM_OS2
1849 if (!Option_CID) {
1850 printf(" You may remove AiR-BOOT manually by entering \"FDISK /MBR\" or \"LVM /NEWMBR:1\"\n");
1851 printf(" in commandline.\n");
1852 }
1853#endif
1854#ifdef PLATFORM_WINNT
1855 if (!Option_CID) {
1856 printf(" You may remove AiR-BOOT manually by entering \"FDISK /MBR\" in commandline.\n");
1857 }
1858#endif
1859 ExitOnly = TRUE;
1860 break;
1861 }
1862 default:
1863 break;
1864 }
1865printf("9> c:%d, s:%d\n", Option_CID, Option_Silent);
1866 if (ExitOnly) {
1867 if (!(Option_CID || Option_Silent)) {
1868 printf("\n");
1869 printf("Please hit ENTER to exit AiR-BOOT installer...\n");
1870 while (getch()!=0x0D);
1871 }
1872 }
1873printf("10> c:%d, s:%d\n", Option_CID, Option_Silent);
1874 // Free the buffer memory.
1875 if (Track0) free(Track0);
1876 if (Bootcode) free(Bootcode);
1877printf("11> c:%d, s:%d\n", Option_CID, Option_Silent);
1878 return 0;
1879}
Note: See TracBrowser for help on using the repository browser.