source: trunk/install/c/install.c@ 60

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

Fixed building on Linux [v1.1.1-testing]

Of course the lowercasing broke building on Linux.
This commit fixes that.

File size: 67.9 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 BOOL 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
605
606 ; Restore ES.
607 pop es
608 }
609
610 return Success;
611 }
612
613 void RebootSystem (void) {
614 _asm {
615 ; 65 * 65536 = 4259840 us = 4.2 sec.
616 mov ax,8600h ; BIOS Wait.
617 xor dx,dx ; Micro seconds Low.
618 mov cx,65 ; Micro seconds High.
619 int 15h ; Transfer to BIOS.
620
621 //~ ; Try reboot via keyboard.
622 //~ mov al,0feh
623 //~ out 64h,al
624
625 ; Otherwise jump to F000:FFF0.
626 db 0EAh
627 dw 0FFF0h
628 dw 0F000h
629 }
630 return;
631 }
632
633#endif
634
635
636
637/*
638// Helper functions -- OS/2 implementation.
639*/
640#ifdef PLATFORM_OS2
641 USHORT CountHarddrives (void) {
642 USHORT NumDrives = 0;
643 if (DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS, &NumDrives, sizeof(NumDrives),NULL, 0) != 0)
644 return 0;
645 return NumDrives;
646 }
647
648 USHORT OS2_GetIOCTLHandle () {
649 USHORT IOCTLHandle = 0;
650 if (DosPhysicalDisk(INFO_GETIOCTLHANDLE, &IOCTLHandle, sizeof(IOCTLHandle),"1:" , 3) != 0)
651 return 0;
652 return IOCTLHandle;
653 }
654
655 void OS2_FreeIOCTLHandle (USHORT IOCTLHandle) {
656 DosPhysicalDisk(INFO_FREEIOCTLHANDLE, NULL, 0, &IOCTLHandle, sizeof(IOCTLHandle));
657 return;
658 }
659
660 // Special feature for OS/2, finds out boot drive letter and sends this
661 // information to AiR-BOOT, so that it's able to set that information
662 // during boot phase. Otherwise the user would have to set this.
663 UCHAR AutoDriveLetter = ' ';
664 ULONG AutoDriveLetterSerial = 0;
665
666 void OS2_GetBootAutoDriveLetter (void) {
667 ULONG BootDrive;
668 struct {
669 ULONG ulVSN;
670 VOLUMELABEL vol;
671 } InfoLevel2;
672 DosQuerySysInfo (QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, &BootDrive, sizeof(BootDrive));
673 // BootDrive - 1-A:, 2-B:, 3-C:
674 if ((BootDrive>2) & (!DosQueryFSInfo(BootDrive, FSIL_VOLSER, (PVOID)(&InfoLevel2), sizeof(InfoLevel2)))) {
675 AutoDriveLetter = (UCHAR) BootDrive+0x7D;
676 AutoDriveLetterSerial = InfoLevel2.ulVSN;
677 if (!Option_CID) {
678 printf("%X\n", InfoLevel2.ulVSN);
679 }
680 }
681 }
682
683 /*
684 // On DOS this geometry check uses the INT13X value for sectors per track.
685 // On OS/2 the DosDevIOCtl call uses a SPT value from the formatted disk,
686 // irrespective of the physical geometry.
687 */
688 BOOL HarddriveCheckGeometry (void) {
689 USHORT IOCTLHandle;
690 USHORT SectorsPerTrack = 0;
691 DEVICEPARAMETERBLOCK DeviceParmBlock;
692 ULONG ulDataLength;
693
694 IOCTLHandle = OS2_GetIOCTLHandle();
695
696 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_GETPHYSDEVICEPARAMS, NULL, 0, NULL, &DeviceParmBlock, sizeof(DeviceParmBlock), &ulDataLength))
697 SectorsPerTrack = DeviceParmBlock.cSectorsPerTrack;
698 OS2_FreeIOCTLHandle (IOCTLHandle);
699 //if (SectorsPerTrack > 61) return TRUE;
700 if (SectorsPerTrack > SECTOR_COUNT) return TRUE;
701 // OS/2 is only able to support 512-byte/sector media, so we dont need to check this
702 return FALSE;
703 }
704
705 BOOL Track0Load (void) {
706 USHORT IOCTLHandle;
707 ULONG TrackLayoutLen = sizeof(TRACKLAYOUT)+sizeof(ULONG)*(SECTOR_COUNT-1);
708 TRACKLAYOUT *TrackLayoutPtr = (TRACKLAYOUT*) malloc(TrackLayoutLen);
709 ULONG cbParms = sizeof(TrackLayoutPtr);
710 ULONG cbData = BYTES_PER_SECTOR;
711 int i;
712 BOOL Success = FALSE;
713
714 IOCTLHandle = OS2_GetIOCTLHandle();
715
716 TrackLayoutPtr->bCommand = 0x01;
717 TrackLayoutPtr->usHead = 0;
718 TrackLayoutPtr->usCylinder = 0;
719 TrackLayoutPtr->usFirstSector = 0;
720 TrackLayoutPtr->cSectors = SECTOR_COUNT;
721
722 for (i=0; i<SECTOR_COUNT; i++) {
723 TrackLayoutPtr->TrackTable[i].usSectorNumber = i+1;
724 TrackLayoutPtr->TrackTable[i].usSectorSize = BYTES_PER_SECTOR;
725 }
726
727 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_READPHYSTRACK,
728 TrackLayoutPtr, cbParms, &cbParms, Track0, cbData, &cbData))
729 Success = TRUE;
730
731 OS2_FreeIOCTLHandle (IOCTLHandle);
732 free (TrackLayoutPtr);
733 return Success;
734 }
735
736 BOOL Track0Write (void) {
737 USHORT IOCTLHandle;
738 ULONG TrackLayoutLen = sizeof(TRACKLAYOUT)+sizeof(ULONG)*(SECTOR_COUNT-1);
739 TRACKLAYOUT *TrackLayoutPtr = (TRACKLAYOUT*) malloc(TrackLayoutLen);
740 ULONG cbParms = sizeof(TrackLayoutPtr);
741 ULONG cbData = BYTES_PER_SECTOR;
742 INT i;
743 BOOL Success = FALSE;
744
745 IOCTLHandle = OS2_GetIOCTLHandle();
746
747
748 TrackLayoutPtr->bCommand = 0x01;
749 TrackLayoutPtr->usHead = 0;
750 TrackLayoutPtr->usCylinder = 0;
751 TrackLayoutPtr->usFirstSector = 0;
752 TrackLayoutPtr->cSectors = SECTOR_COUNT;
753
754 for (i=0; i<SECTOR_COUNT; i++) {
755 TrackLayoutPtr->TrackTable[i].usSectorNumber = i+1;
756 TrackLayoutPtr->TrackTable[i].usSectorSize = BYTES_PER_SECTOR;
757 }
758
759 if (!DosDevIOCtl(IOCTLHandle, IOCTL_PHYSICALDISK, PDSK_WRITEPHYSTRACK,
760 TrackLayoutPtr, cbParms, &cbParms, Track0, cbData, &cbData))
761 Success = TRUE;
762
763 OS2_FreeIOCTLHandle (IOCTLHandle);
764 free (TrackLayoutPtr);
765 return Success;
766 }
767
768 #define CATEGORY_DOSSYS 0xD5
769 #define FUNCTION_REBOOT 0xAB
770
771 void RebootSystem (void) {
772 HFILE DosHandle;
773 ULONG DosOpenAction;
774
775 DosSleep (2000);
776 if (!DosOpen("DOS$", &DosHandle, &DosOpenAction, 0, FILE_NORMAL, FILE_OPEN, OPEN_ACCESS_READWRITE|OPEN_SHARE_DENYNONE, NULL)) {
777 DosDevIOCtl(DosHandle, CATEGORY_DOSSYS, FUNCTION_REBOOT, NULL, 0, NULL, NULL, 0, NULL);
778 DosSleep (60000);
779 }
780 DosClose(DosHandle);
781 }
782#endif
783
784
785
786
787/*
788// Helper functions -- Win32 implementation.
789*/
790#ifdef PLATFORM_WINNT
791 // Checks, if we are under NT
792 BOOL CheckWindowsVersion (void) {
793 OSVERSIONINFO Version;
794 Version.dwOSVersionInfoSize = sizeof(Version);
795 GetVersionEx(&Version);
796 if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
797 return TRUE;
798 if (!Option_CID) {
799 printf(" - This installer is for WindowsNT family only.\n");
800 printf(" Please use DOS installer for Windows9x.\n");
801 }
802 return FALSE;
803 }
804
805
806 HANDLE WINNT_GetIOCTLHandle (void) {
807 return CreateFile("\\\\.\\physicaldrive0", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
808 }
809
810 void WINNT_FreeIOCTLHandle (HANDLE IOCTLHandle) {
811 CloseHandle(IOCTLHandle);
812 }
813
814 USHORT CountHarddrives (void) {
815 return 1;
816 }
817
818 BOOL HarddriveCheckGeometry (void) {
819 HANDLE IOCTLHandle;
820 DISK_GEOMETRY Geometry;
821 USHORT SectorsPerTrack = 0;
822 DWORD Dummy;
823
824 IOCTLHandle = WINNT_GetIOCTLHandle();
825 if (DeviceIoControl(IOCTLHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Geometry, sizeof(Geometry), &Dummy, NULL))
826 SectorsPerTrack = (USHORT) Geometry.SectorsPerTrack;
827 WINNT_FreeIOCTLHandle(IOCTLHandle);
828 //if (SectorsPerTrack > 61) return TRUE; // >60 should also be ok for normal image (60 for image 1 for lvm)
829 if (SectorsPerTrack > SECTOR_COUNT)
830 return TRUE; // Note: This is 1 sector smaller than above !!
831
832 return FALSE;
833 }
834
835 BOOL Track0Load (void) {
836 HANDLE IOCTLHandle;
837 DWORD BytesRead = 0;
838 BOOL Success = FALSE;
839
840 IOCTLHandle = WINNT_GetIOCTLHandle();
841 SetFilePointer(IOCTLHandle, 0, 0, FILE_BEGIN);
842 if (ReadFile(IOCTLHandle, Track0, SECTOR_COUNT * BYTES_PER_SECTOR, &BytesRead, NULL))
843 Success = TRUE;
844 WINNT_FreeIOCTLHandle(IOCTLHandle);
845 return Success;
846 }
847
848 BOOL Track0Write (void) {
849 HANDLE IOCTLHandle;
850 DWORD BytesWritten = 0;
851 BOOL Success = FALSE;
852
853 IOCTLHandle = WINNT_GetIOCTLHandle();
854 SetFilePointer(IOCTLHandle, 0, 0, FILE_BEGIN);
855 if (WriteFile(IOCTLHandle, Track0, SECTOR_COUNT * BYTES_PER_SECTOR, &BytesWritten, NULL))
856 Success = TRUE;
857 WINNT_FreeIOCTLHandle(IOCTLHandle);
858 return Success;
859 }
860
861 void RebootSystem (void) {
862 HANDLE token;
863 TOKEN_PRIVILEGES tokenpriv;
864 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &token);
865 LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tokenpriv.Privileges[0].Luid);
866 tokenpriv.PrivilegeCount = 1;
867 tokenpriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
868 AdjustTokenPrivileges(token, FALSE, &tokenpriv, 0, NULL, 0);
869 ExitWindowsEx(EWX_REBOOT, 0);
870 }
871#endif
872
873
874/*
875// Helper functions -- Linux implementation.
876*/
877#ifdef PLATFORM_LINUX
878 USHORT CountHarddrives (void) {
879 USHORT NumDrives = 0;
880 // Implement !
881 return NumDrives;
882 }
883
884 BOOL HarddriveCheckGeometry (void) {
885
886 // Implement !
887 return FALSE;
888 }
889
890 BOOL Track0Load (void) {
891 BOOL Success = FALSE;
892
893 // Implement !
894 return Success;
895 }
896
897 BOOL Track0Write (void) {
898 BOOL Success = FALSE;
899
900 // Implement !
901 return Success;
902 }
903
904 void RebootSystem (void) {
905
906 // Implement !
907 }
908
909#endif
910
911
912
913
914
915// ============================================================================
916// Common Code
917// ============================================================================
918
919
920USHORT GetChecksumOfSector (USHORT Checksum, PCHAR SectorPtr) {
921 PUSHORT TempPtr = (PUSHORT)SectorPtr;
922 USHORT i;
923 for (i=0; i<256; i++) {
924 Checksum = *TempPtr ^ 0xBABE ^ Checksum;
925 TempPtr++;
926 }
927 if (Checksum==0)
928 Checksum = 1;
929 return Checksum;
930}
931
932// Loads airboot.bin into memory (if possible) and sets some variables
933// also makes sure that airboot.bin has correct length
934BOOL LoadBootcodeFromFile (void) {
935 FILE *FileHandle = NULL;
936 ULONG BootcodeSize = 0;
937
938 // Try to open file...
939 FileHandle = fopen(IMAGE_NAME, "rb");
940 if (!FileHandle) {
941 if (!Option_CID) {
942 printf("%s not found\n", IMAGE_NAME);
943 }
944 return FALSE;
945 }
946
947 // Seek to end of file to determine image size...
948 fseek (FileHandle, 0, SEEK_END);
949 BootcodeSize = ftell(FileHandle);
950 if (BootcodeSize!=IMAGE_SIZE && BootcodeSize!=IMAGE_SIZE_60SECS) {
951 fclose (FileHandle);
952 if (!Option_CID) {
953 printf("Invalid %sn\n", IMAGE_NAME);
954 }
955 return FALSE;
956 }
957
958 // Read whole file into memory...
959 fseek (FileHandle, 0, SEEK_SET);
960 fread (Bootcode, 1, IMAGE_SIZE, FileHandle);
961 fclose (FileHandle);
962
963 // Extract language and version info...
964 Bootcode_Version = (Bootcode[13] << 8) | Bootcode[14];
965 Bootcode_LanguageID = Bootcode[15];
966 Bootcode_ConfigVersion = (Bootcode[0x6C0D] << 8) | Bootcode[0x6C0E];
967 return TRUE;
968}
969
970/**
971 * Check MBR and AB signatures.
972 * Also check code sectors if AB is installed.
973 * Set global status accordingly.
974 */
975void Status_CheckCode (void) {
976 USHORT TotalCodeSectorsUsed = 0;
977 USHORT Checksum = 0;
978 PCHAR SectorPtr = NULL;
979
980 if (Status_Code==STATUS_IMPOSSIBLE)
981 return;
982 // EZ-Setup check!
983 Status_Code = STATUS_NOTINSTALLED;
984 if ((Track0[0x1FE]!=0x55) || (Track0[0x1FF]!=0xAA))
985 return; // No MBR signature found, so not installed
986 if (strncmp(&Track0[2], "AiRBOOT", 7)!=0)
987 return; // No AiR-BOOT signature found, so not installed
988 // MBR and AiR-BOOT signature found...
989 TotalCodeSectorsUsed = Track0[0x10]; // 34h/52 in v1.06
990 SectorPtr = &Track0[1 * BYTES_PER_SECTOR]; // Start at sector 2
991 // Calculate checksum of code-sectors
992 while (TotalCodeSectorsUsed>0) {
993 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
994 SectorPtr += BYTES_PER_SECTOR;
995 TotalCodeSectorsUsed--;
996 }
997 if (Checksum!=*(PUSHORT) &Track0[0x11]) {
998 Status_Code = STATUS_CORRUPT;
999 return; // Bad checksum for code
1000 }
1001 // Checksum fine...
1002 Installed_LanguageID = Track0[0x0F];
1003 Installed_CodeVersion = (Track0[0x0D] << 8) | Track0[0x0E];
1004 if (Installed_CodeVersion < Bootcode_Version)
1005 Status_Code = STATUS_INSTALLEDMGU; // Do upgrade
1006 else
1007 Status_Code = STATUS_INSTALLED; // Same version installed
1008
1009 return;
1010}
1011
1012
1013void Status_CheckConfig (void) {
1014 PCHAR ConfigSectorPtr = &Track0[CONFIG_OFFSET]; // Config sector offset hard-coded !
1015 PCHAR SectorPtr = NULL;
1016 USHORT Checksum = 0;
1017 USHORT ConfigChecksum = 0;
1018 USHORT SectorCount = 0;
1019
1020 /*
1021 // Note that the 'AiRCFG-TABLE' string includes the invisible 0xAD char.
1022 */
1023 if (strncmp(ConfigSectorPtr, "AiRCFG-TABLE­", 13)==0) {
1024 // AiR-BOOT signature found...
1025 SectorPtr = &Track0[54 * BYTES_PER_SECTOR]; // Start at sector 55
1026 ConfigChecksum = *(PUSHORT)&Track0[54 * BYTES_PER_SECTOR + 20];
1027 // Remove checksum
1028 *(PUSHORT)&Track0[54 * BYTES_PER_SECTOR + 20] = 0; // Config sector secnum hard-coded !
1029
1030 /*
1031 // Rousseau: # Keep compatible with v1.07 CRC #
1032 // AB v1.07 had bugs in writing the wrong number of AB config sectors.
1033 // This is fixed in v1.0.8 but the CRC has to be calculated the "v1.07 way"
1034 // otherwise v1.07 SET(A)BOOT and INSTALL2.EXE will think the AB config
1035 // is corrupted.
1036 // So the CRC is calculated over 5 sectors instead of 7.
1037 */
1038 SectorCount = 5;
1039
1040 while (SectorCount>0) {
1041 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1042 SectorPtr += BYTES_PER_SECTOR;
1043 SectorCount--;
1044 }
1045 // Restore checksum
1046 *(PUSHORT) &Track0[54 * BYTES_PER_SECTOR + 20] = ConfigChecksum; // Config sector secnum hard-coded !
1047 if (Checksum != ConfigChecksum) {
1048 Status_Config = STATUS_CORRUPT;
1049 return;
1050 }
1051 // Checksum fine
1052 Installed_ConfigVersion = (Track0[54 * BYTES_PER_SECTOR + 0x0D] << 8) | Track0[54 * BYTES_PER_SECTOR + 0x0E];
1053 if (Installed_ConfigVersion >= Bootcode_ConfigVersion) {
1054 Status_Config = STATUS_INSTALLED;
1055 return;
1056 }
1057 Status_Config = STATUS_INSTALLEDMGU;
1058
1059 // Abort if unknown installed config version.
1060 if ((Installed_ConfigVersion > 0x110)) {
1061 if (!Option_CID) {
1062 printf("\n");
1063 printf("Configuration version of installed AiR-BOOT not supported by this installer !\n");
1064 printf("\n");
1065 }
1066 exit(1);
1067 }
1068
1069 // Abort if unknown to-install config version.
1070 if ((Bootcode_ConfigVersion > 0x110)) {
1071 if (!Option_CID) {
1072 printf("\n");
1073 printf("Configuration version of new AiR-BOOT.BIN not supported by this installer !\n");
1074 printf("\n");
1075 }
1076 exit(1);
1077 }
1078
1079
1080 // Those upgrades will copy useful configuration data to the image config
1081 // If new configuration data was added, those spaces are not overwritten
1082 // Sector 60 (MBR-BackUp) *MUST BE* copied, otherwise it would be lost.
1083 // Rousseau: Upgrade from v0.27
1084 if (Installed_ConfigVersion <= 0x27) {
1085 // UPGRADE v0.27 and prior versions
1086
1087 // Sector 55
1088 // Changes: Offset 69 length 75 - Linux command line
1089 // Offset 144 length 1 - Linux kernel partition
1090 // Offset 145 Length 11 - Default kernel name
1091 // Offset 156 Length 1 - Kernel name terminator 1
1092 // Offset 157 Length 11 - Last kernel name
1093 // Offset 168 Length 1 - Kernel name terminator 2
1094 // Offset 169 Length 1 - Ext. partition M$-hack enable
1095 // -> Total-length 101
1096 // Offset 432 Length 34 - New IPT entry (BIOS continued)
1097 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], 69 - 16); // CHECKEN !!
1098 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 466], &Track0[54 * BYTES_PER_SECTOR + 466], 46); // CHECKEN !!
1099 // Sector 56-57 no changes
1100 memcpy(&Bootcode[55*512], &Track0[55 * BYTES_PER_SECTOR], 1024);
1101 // Sector 58-59
1102 // Changes: Offset 900 Length 30 - Logical driveletter table
1103 memcpy(&Bootcode[57 * BYTES_PER_SECTOR], &Track0[57 * BYTES_PER_SECTOR], 900); // AANPASSEN 900 !!
1104 // Sector 60 copy unmodified
1105 memcpy(&Bootcode[59 * BYTES_PER_SECTOR], &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // CHECKEN !!
1106 return;
1107 }
1108 // Rousseau: Upgrade from v0.91
1109 if (Installed_ConfigVersion <= 0x91) {
1110 // UPGRADE v0.91 and prior versions
1111 // Sector 55-57 no changes
1112 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR + 1024 - 16); // CHACKEN !!
1113 // Sector 58-59
1114 // Changes: Offset 900 Length 30 - Logical driveletter table
1115 memcpy(&Bootcode[57 * BYTES_PER_SECTOR], &Track0[57 * BYTES_PER_SECTOR], 900); // AANPASSEN 900 !!
1116 // Sector 60/62 copy unmodified
1117 memcpy(&Bootcode[59 * BYTES_PER_SECTOR], &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR);
1118 return;
1119 }
1120
1121
1122 // UPGRADE to v1.06 format.
1123 // We don't need to "upgrade" the configuration to move to v1.06, we simply copy it over.
1124 // From Sector 55, 6 sectors in total but never header/version.
1125 // Rousseau: We copy two more sectors (8 in total) in the extended (45 partition) version.
1126 switch (IMAGE_SIZE) {
1127 case IMAGE_SIZE_60SECS: {
1128 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR * 6 - 16);
1129 break;
1130 }
1131 case IMAGE_SIZE_62SECS: {
1132 memcpy(&Bootcode[54 * BYTES_PER_SECTOR + 16], &Track0[54 * BYTES_PER_SECTOR + 16], BYTES_PER_SECTOR * 8 - 16);
1133 break;
1134 }
1135 }
1136
1137 /*
1138 // Convert v1.06 hideparttable (30x30) to the v1.07 (30x45) format.
1139 // Also copy drive-letters to either v1.07 or v1.0.8+ location.
1140 */
1141 if ((Installed_ConfigVersion == 0x102) && (Bootcode_ConfigVersion >= 0x107)) {
1142 int i,j;
1143 char c;
1144 //printf("Converting 1.06 -> 1.07 hidepart");
1145 // Copy old hide-part table to new location.
1146 memcpy(&Bootcode[0x7400], &Track0[0x7200], 900);
1147 // Setup temporary table.
1148 memset(TempHidPartTable, 0xff, 45 * 34);
1149 // Copy old hide-part table to temporary table.
1150 for (i=0; i<30; i++) {
1151 for (j=0; j<30; j++) {
1152 c = Bootcode[0x7400+i*30+j];
1153 TempHidPartTable[i*45+j] = c;
1154 }
1155 }
1156 // Copy temporary table to final v1.07 location.
1157 memcpy(&Bootcode[0x7400], TempHidPartTable, 30 * 45);
1158
1159 // Clear drive-letters if version being installed is v1.07.
1160 if (Bootcode_ConfigVersion == 0x107) {
1161 memset(&Bootcode[0x7946], 0, 45);
1162 }
1163
1164 // Copy over drive-letters from v1.06 location to v1.08+ location.
1165 if ((Bootcode_ConfigVersion >= 0x108) && (Bootcode_ConfigVersion <= 0x110)) {
1166 memset(&Bootcode[0x6cb0], 0, 45);
1167 memcpy(&Bootcode[0x6cb0], &Track0[0x7584], 30);
1168 }
1169 }
1170
1171 /*
1172 // Convert v1.07 hideparttable (30x45) to a packed v1.0.8+ (45x45) format.
1173 */
1174 if ((Installed_ConfigVersion < 0x108) && (Bootcode_ConfigVersion <= 0x110)) {
1175 int i,j;
1176 char c;
1177 //printf("Converting to 1.08 packed hidepart");
1178 // Setup temporary table.
1179 memset(TempHidPartTable, 0xff, 45 * 34);
1180
1181 // Copy old hide-part table to temporary table.
1182 // Unpacked table is 30 rows with 45 columns per row.
1183 // Packed table is 45 rows with 45 columns per row packed in 34 bytes.
1184 for (i=0; i<30; i++) {
1185 for (j=0; j<45; j++) {
1186 c = Bootcode[0x7400+i*45+j]; // Get unpacked value
1187 c = set_bitfield(&TempHidPartTable[i*34], j, 6, c); // Store 6-bit packed value
1188 }
1189 }
1190 // Copy temporary table to final v1.0.8+ location (packed format)
1191 memcpy(&Bootcode[0x7400], TempHidPartTable, 45 * 34);
1192 // Show LVM Drive Letters.
1193 Bootcode[0x6c17] = 1;
1194 }
1195
1196 return;
1197 }
1198 // MKW:
1199 // Check for prior v0.26 signature
1200 // not supported in C version anymore
1201 // Don't have this version here for testing and I can't risk breaking
1202 // configuration
1203 return;
1204}
1205
1206// Checks partition table for valid data
1207BOOL Virus_CheckThisMBR (PCHAR MBRptr) { // Rousseau: adjusted this function
1208 USHORT PartitionNo;
1209 ////ULONG CHSStart, CHSEnd;
1210
1211 //printf("DEBUG: Virus_CheckThisMBR\n");
1212
1213 if (*(PUSHORT)(MBRptr + BYTES_PER_SECTOR - 2)!=0x0AA55)
1214 return FALSE;
1215
1216 //printf("DEBUG: Virus_CheckThisMBR - Checking Partitions\n");
1217
1218 MBRptr += 446;
1219 for (PartitionNo=0; PartitionNo<4; PartitionNo++) {
1220 if (*(MBRptr+4) != 0) {
1221 /*
1222 // Rousseau 2011-02-04: ## Check for GPT ##
1223 */
1224 if (*(MBRptr+4) == GPT) {
1225 if (!Option_CID) {
1226 printf("ERROR: This drive is partitioned with the modern GPT layout.\n");
1227 printf(" AiR-BOOT is currently unable to handle GPT partitioned drives.\n");
1228 printf(" Installation aborted, no changes made.\n");
1229 }
1230 exit(2);
1231 }
1232
1233 /*
1234 // Rousseau: 2011-05-05
1235 // Last minute change to have AB install on a disk
1236 // with nopartitions on the it. (check !)
1237 // It still checks for GPT but will skip the check below.
1238 */
1239 continue;
1240
1241 //printf("DEBUG: Virus_CheckThisMBR - Partition: %d\n", PartitionNo);
1242 // Partition-type defined, analyse partition data
1243 ////CHSStart = (*(MBRptr+3) | ((*(MBRptr+2) >> 6) << 8)) << 16; // Cylinder
1244 ////CHSStart |= (*(MBRptr+2) & 0x3F) | ((*(MBRptr+1) << 8)); // Sector / Head
1245 //printf("DEBUG: Virus_CheckThisMBR - CHSStart: %d\n", CHSStart); // 3F MASK CHECKEN !!
1246
1247 ////CHSEnd = (*(MBRptr+7) | ((*(MBRptr+6) >> 6) << 8)) << 16; // Cylinder
1248 ////CHSEnd |= (*(MBRptr+6) & 0x3F) | ((*(MBRptr+5) << 8)); // Sector / Head
1249 //printf("DEBUG: Virus_CheckThisMBR - CHSEnd: %d\n", CHSEnd);
1250
1251
1252 /*
1253 // Rousseau 2011-02-03: ## Changed below from < to <= ##
1254 // When a partition is above 1024x255x63 (8GiB) the start and end of the partition
1255 // in the MBR is the same (1024/255/63) to indicate extended CHS-values.
1256 // This made the installer see this as a non-valid entry.
1257 // Fixme: This could use some further optimazation like checking if CHS is really 1024/255/63
1258 // to exclude truly faulty partition-entries.
1259 // Also depends on conventions: IBM,MS,Partition Magic,...
1260 */
1261 /*if (CHSStart<CHSEnd) {*/
1262 ////if (CHSStart<=CHSEnd) {
1263 //// if (*(PULONG)(MBRptr+12)!=0) // Absolute length > 0?
1264 //// return TRUE;
1265 ////}
1266 }
1267 // Go to next partition
1268 MBRptr += 16;
1269 }
1270 // No partitions defined/no valid partitions found
1271 // Rousseau: Still return TRUE (OK)
1272 //return FALSE;
1273 return TRUE;
1274}
1275
1276BOOL Virus_CheckCurrentMBR (void) {
1277 return Virus_CheckThisMBR((PCHAR) Track0);
1278}
1279
1280BOOL Virus_CheckForBackUpMBR (void) {
1281 BOOL bMbrBackup = FALSE;
1282
1283 // All versions above v1.06 have expanded tables so the MBR-backup
1284 // is located 2 sectors higher in the track0 image.
1285 if (Installed_ConfigVersion <= 0x0106)
1286 bMbrBackup = Virus_CheckThisMBR((PCHAR) &Track0[59 * BYTES_PER_SECTOR]);
1287 else
1288 bMbrBackup = Virus_CheckThisMBR((PCHAR) &Track0[61 * BYTES_PER_SECTOR]);
1289
1290 return bMbrBackup;
1291}
1292
1293BOOL Virus_CheckForStealth (void) {
1294 PCHAR CurPtr = (PCHAR) Track0;
1295 USHORT i;
1296
1297 for (i=0; i<511; i++) {
1298 if (*(PUSHORT)CurPtr == 0x13CD) return FALSE;
1299 CurPtr++;
1300 }
1301 // No CD13h found? possible stealth
1302 return TRUE;
1303}
1304
1305// Copies backup MBR into current MBR on current memory copy of track 0
1306// Rousseau: Two sectors higher in the extended version.
1307void Virus_CopyBackUpMBR (void) {
1308 switch (IMAGE_SIZE) {
1309 case IMAGE_SIZE_60SECS: {
1310 memcpy(Track0, &Track0[59 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // sector 60
1311 break;
1312 }
1313 case IMAGE_SIZE_62SECS: {
1314 memcpy(Track0, &Track0[61 * BYTES_PER_SECTOR], BYTES_PER_SECTOR); // sector 62
1315 break;
1316 }
1317 }
1318}
1319
1320void Status_PrintF (ULONG Status, USHORT Version) {
1321 switch (Status) {
1322 case STATUS_NOTINSTALLED: {
1323 if (!Option_CID) {
1324 printf("not installed\n");
1325 }
1326 break;
1327 }
1328 case STATUS_CORRUPT: {
1329 if (!Option_CID) {
1330 printf("not intact\n");
1331 }
1332 break;
1333 }
1334 case STATUS_INSTALLED:
1335 case STATUS_INSTALLEDMGU:
1336 if (!Option_CID) {
1337 printf("intact (v%x.%1d.%1d)", Version>>8, (Version & 0x0F0)>>4, Version & 0x0F);
1338 }
1339 if (Status==STATUS_INSTALLEDMGU)
1340 if (!Option_CID) {
1341 printf(", but may be updated");
1342 }
1343 if (!Option_CID) {
1344 printf("\n");
1345 }
1346 break;
1347
1348 case STATUS_IMPOSSIBLE:
1349 if (!Option_CID) {
1350 printf(ImpossibleCause);
1351 }
1352 break;
1353 }
1354}
1355
1356void Language_PrintF(UCHAR LanguageID) {
1357 if (Option_CID)
1358 return;
1359 switch (LanguageID) {
1360 case 'E': printf("english"); break;
1361 case 'N': printf("dutch"); break; // Changed from 'D' to 'N'
1362 case 'G': printf("german"); break;
1363 case 'F': printf("french"); break;
1364 case 'I': printf("italian"); break;
1365 case 'R': printf("russian"); break;
1366 case 'S': printf("swedish"); break;
1367 default: printf("unknown");
1368 }
1369}
1370
1371// Doesn't actually write code/config, but writes it to track0 memory
1372void Install_WriteCode (void) {
1373 USHORT TotalCodeSectorsUsed = 0;
1374 USHORT SectorCount = 0;
1375 USHORT Checksum = 0;
1376 PCHAR SectorPtr = NULL;
1377
1378 // Calculate checksum for code...
1379 TotalCodeSectorsUsed = Bootcode[0x10]; // SECTORS USED CHECKEN !! (34h / 52d in v1.06)
1380 SectorPtr = &Bootcode[1 * BYTES_PER_SECTOR]; // Start at sector 2
1381 SectorCount = TotalCodeSectorsUsed;
1382 while (SectorCount>0) {
1383 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1384 SectorPtr += BYTES_PER_SECTOR;
1385 SectorCount--;
1386 }
1387 *(PUSHORT)&Bootcode[0x11] = Checksum;
1388
1389 // Copy MBR till offset 0x1B8 (Windows NT hdd signature location)
1390 memcpy(Track0, Bootcode, 0x1B8);
1391
1392 // Copy over code sectors...
1393 memcpy(&Track0[BYTES_PER_SECTOR], &Bootcode[BYTES_PER_SECTOR], TotalCodeSectorsUsed * BYTES_PER_SECTOR);
1394}
1395
1396void Install_WriteConfig (void) {
1397 USHORT SectorCount = 0;
1398 USHORT Checksum = 0;
1399 PCHAR SectorPtr = NULL;
1400
1401#ifdef PLATFORM_OS2
1402 if (AutoDriveLetter!=0) {
1403 // Add DriveLetter Automatic veriables, if set
1404 Bootcode[54 * BYTES_PER_SECTOR + 0x1AB] = AutoDriveLetter; // CHECKEN !
1405 *(PULONG)&Bootcode[54 * BYTES_PER_SECTOR + 0x1AC] = AutoDriveLetterSerial;
1406 }
1407#endif
1408
1409 // Delete current checksum
1410 *(PUSHORT)&Bootcode[54 * BYTES_PER_SECTOR + 20] = 0;
1411
1412 SectorPtr = &Bootcode[54 * BYTES_PER_SECTOR]; // Start at sector 55
1413
1414 /*
1415 // Rousseau: # Keep compatible with v1.07 CRC #
1416 // AB v1.07 had bugs in writing the wrong number of AB config sectors.
1417 // This is fixed in v1.0.8+ but the CRC has to be calculated the "v1.07 way"
1418 // otherwise v1.07 SET(A)BOOT and AIRBOOT2.EXE will think the AB config
1419 // is corrupted.
1420 // So the CRC is calculated over 5 sectors instead of 7.
1421 */
1422 SectorCount = 5;
1423
1424 while (SectorCount>0) {
1425 Checksum = GetChecksumOfSector(Checksum, SectorPtr);
1426 SectorPtr += BYTES_PER_SECTOR;
1427 SectorCount--;
1428 }
1429 *(PUSHORT)&Bootcode[54 * BYTES_PER_SECTOR + 20] = Checksum;
1430
1431 // Copy configuration sectors
1432 // Rousseau: Two more sectors for extended version.
1433 switch (IMAGE_SIZE) {
1434 case IMAGE_SIZE_60SECS: {
1435 memcpy(&Track0[54 * BYTES_PER_SECTOR], &Bootcode[54 * BYTES_PER_SECTOR], 6 * BYTES_PER_SECTOR);
1436 break;
1437 }
1438 case IMAGE_SIZE_62SECS: {
1439 memcpy(&Track0[54 * BYTES_PER_SECTOR], &Bootcode[54 * BYTES_PER_SECTOR], 8 * BYTES_PER_SECTOR);
1440 break;
1441 }
1442 }
1443
1444 return;
1445}
1446
1447
1448void DumpTrack0() {
1449 int i,j;
1450 for (i=27; i<32; i++) {
1451 for (j=0; j<16; j++) {
1452 printf("%02X",Track0[i*16+j]);
1453 }
1454 printf("\n");
1455 }
1456}
1457
1458
1459
1460
1461void DoDebug() {
1462 USHORT t0codv = 0;
1463 USHORT t0cfgv = 0;
1464 USHORT bccodv = 0;
1465 USHORT bccfgv = 0;
1466
1467 //do_bf_test();
1468
1469 printf("\nHardisks : %d\n", CountHarddrives());
1470 printf("\nGEO : %d\n", HarddriveCheckGeometry());
1471 printf("\nTrack0 : %d\n", Track0Load());
1472 printf("\nBootcode : %d\n", LoadBootcodeFromFile());
1473
1474
1475 // Dump Track0
1476 DumpTrack0();
1477 printf("\n\n");
1478 // Dump Bootcode
1479 //~ {
1480 //~ int i;
1481 //~ for (i=0; i<512; i++) {
1482 //~ printf("%02X",Bootcode[i]);
1483 //~ }
1484 //~ }
1485 //~ printf("\n\n");
1486
1487 t0codv = Track0[13] << 8 | Track0[14];
1488 printf("t0codv : %04X\n", t0codv);
1489
1490 t0cfgv = Track0[0x6c00+13] << 8 | Track0[0x6c00+14];
1491 printf("t0cfgv : %04X\n", t0cfgv);
1492
1493 bccodv = Bootcode[13] << 8 | Bootcode[14];
1494 printf("bccodv : %04X\n", bccodv);
1495
1496 bccfgv = Bootcode[0x6c00+13] << 8 | Bootcode[0x6c00+14];
1497 printf("bccfgv : %04X\n", bccfgv);
1498
1499 return;
1500
1501}
1502
1503
1504// ============================================================================
1505// Main Entrypoint
1506// ============================================================================
1507
1508
1509
1510#define MAXCMDPARMLEN 11
1511
1512int main (int argc, char **argv) {
1513 ULONG CurArgument = 0;
1514 size_t ArgumentLen = 0;
1515 PCHAR StartPos = 0;
1516 UCHAR UserKey = ' ';
1517 BOOL ExitOnly = FALSE;
1518 CHAR TempSpace[MAXCMDPARMLEN+1];
1519
1520
1521 // Check commandline parameters
1522 CurArgument = 1;
1523 while (CurArgument<argc) {
1524 StartPos = argv[CurArgument];
1525 ArgumentLen = strlen(StartPos);
1526
1527 if (((*StartPos=='-') || (*StartPos=='/')) && (ArgumentLen>1)) {
1528 StartPos++; ArgumentLen--;
1529 if (ArgumentLen>MAXCMDPARMLEN)
1530 ArgumentLen = MAXCMDPARMLEN;
1531 strncpy((char *) TempSpace, StartPos, ArgumentLen);
1532 TempSpace[ArgumentLen] = 0;
1533 StartPos = (PCHAR) TempSpace;
1534 while (*StartPos!=0) {
1535 *StartPos = tolower(*StartPos); StartPos++;
1536 }
1537 if (strcmp((char *) TempSpace, "forcecode")==0) Option_ForceCode = TRUE;
1538 if (strcmp((char *) TempSpace, "forceconfig")==0) Option_ForceConfig = TRUE;
1539 if (strcmp((char *) TempSpace, "silent")==0) Option_Silent = TRUE;
1540 if (strcmp((char *) TempSpace, "cid")==0) Option_CID = TRUE;
1541 }
1542 CurArgument++;
1543 }
1544
1545
1546// Only support /cid on OS/2 for the moment.
1547// The DOS code behaves quirky with /cid and Win32 is not tested at all.
1548#ifndef PLATFORM_OS2
1549 Option_CID = FALSE;
1550#endif
1551
1552 if (Option_CID) {
1553 Option_Silent = TRUE;
1554 }
1555
1556
1557 // Show header.
1558 if (!Option_CID) {
1559 printf("AiR-BOOT Installer v%s.%s.%s for %s\n",
1560 BLDLVL_MAJOR_VERSION,
1561 BLDLVL_MIDDLE_VERSION,
1562 BLDLVL_MINOR_VERSION,
1563 PLATFORM_NAME);
1564 printf(" - (c) Copyright 1998-2012 by Martin Kiewitz.\n");
1565 printf("\n-> ...Please wait... <-\n");
1566 }
1567
1568
1569 // Allocate buffers for Track0 and 'airboot.bin'.
1570 Track0 = malloc(SECTOR_COUNT * BYTES_PER_SECTOR);
1571 Bootcode = malloc(SECTOR_COUNT * BYTES_PER_SECTOR);
1572
1573
1574 // Exit of allocation failed.
1575 if (!(Track0 && Bootcode)) {
1576 if (!Option_CID) {
1577 printf("- Unable to allocate enough memory, operation aborted!\n");
1578 }
1579 exit(4);
1580 }
1581
1582
1583 //~ DoDebug();
1584 //~ exit(0);
1585
1586
1587#ifdef PLATFORM_WINNT
1588 if (CheckWindowsVersion()==FALSE)
1589 return 1;
1590#endif
1591
1592 if (CountHarddrives()==0) {
1593 if (!Option_CID) {
1594 printf(" - No physical drives found on this system. Install impossible.\n");
1595 }
1596 return 3; // Rouseau: changed from 1 to 3
1597 }
1598
1599 if (!Option_CID) {
1600 printf(" - Loading bootcode from file...");
1601 }
1602
1603 if (LoadBootcodeFromFile()==FALSE)
1604 return 1;
1605
1606 if (!Option_CID) {
1607 printf("ok\n");
1608 }
1609
1610 if (!Option_CID) {
1611 printf(" - Loading MBR from harddisc...");
1612 }
1613
1614
1615 if (!Track0Load()) {
1616 if (!Option_CID) {
1617 printf("LOAD ERROR!\n");
1618 }
1619 return 1;
1620 }
1621 else {
1622 if (!Option_CID) {
1623 printf("ok\n");
1624 }
1625 }
1626
1627 if (!HarddriveCheckGeometry()) {
1628 // No EZ-SETUP check here, because we are under 32-bit OS and this
1629 // wouldn't make any sense
1630 //printf("\nDEBUG: STATUS_IMPOSSIBLE\n");
1631 Status_Code = STATUS_IMPOSSIBLE;
1632 ImpossibleCause = "unable to install\n Your harddisc does not have at least 63 sectors per track.";
1633 }
1634
1635
1636 if (!Option_CID) {
1637 printf("\n-> ...Current Status... <-\n");
1638 }
1639
1640 Status_CheckCode();
1641 if (!Option_CID) {
1642 printf(" - AiR-BOOT is ");
1643 }
1644 Status_PrintF(Status_Code, Installed_CodeVersion);
1645 if (Status_Code==STATUS_IMPOSSIBLE)
1646 return 1;
1647 Status_CheckConfig();
1648 if (!Option_CID) {
1649 printf(" - Configuration is ");
1650 }
1651 Status_PrintF(Status_Config, Installed_ConfigVersion);
1652 // Display language as well, if code installed
1653 if ((Status_Code==STATUS_INSTALLED) || (Status_Code==STATUS_INSTALLEDMGU)) {
1654 if (!Option_CID) {
1655 printf(" - Language is ");
1656 }
1657 Language_PrintF(Installed_LanguageID);
1658 if (!Option_CID) {
1659 printf("\n");
1660 }
1661 }
1662
1663 // =============================================================
1664 // PRE-CHECKING, WHAT WE ARE SUPPOSED TO DO...
1665 // =============================================================
1666 if ((Option_ForceCode) || (Status_Code!=STATUS_INSTALLED) || (Installed_LanguageID!=Bootcode_LanguageID))
1667 Install_Code = TRUE; // If LanguageID different or not installed
1668 if ((Option_ForceConfig) || (Status_Config!=STATUS_INSTALLED))
1669 Install_Config = TRUE; // If not installed
1670
1671 if ((Status_Code==STATUS_CORRUPT) || (Status_Config==STATUS_CORRUPT))
1672 Install_IsCorrupt = TRUE; // If anything is corrupt
1673
1674 // =============================================================
1675 // VIRUS
1676 // =============================================================
1677 // If-Table
1678 // ---------
1679 // Code==not installed, Config=not installed -> Check MBR
1680 // Code==installed, config==installed -> Check MBR (-> Virus?)
1681 // Code==not installed, config==installed -> (-> Virus?)
1682 // Code==installed, config==not installed -> Check MBR (-> Virus?)
1683
1684 //printf("DEBUG: Status_Code: %d, Status_Config: %d\n", Status_Code, Status_Config); // Rousseau: DEBUG
1685
1686 if ((Status_Code==STATUS_NOTINSTALLED) & (Status_Config==STATUS_NOTINSTALLED)) {
1687 // Nothing installed, so check MBR, if squashed...
1688 if (!Virus_CheckCurrentMBR()) {
1689 if (!Option_CID) {
1690 printf("\n\n");
1691 printf("AiR-BOOT detected that the data on your harddisc got damaged.\n");
1692 printf("If you had AiR-BOOT installed before: the corruption killed AiR-BOOT completly!\n");
1693 printf("Installation halted.\n");
1694 }
1695 return 255; // Rousseau: changed from 1 to 255
1696 }
1697 //printf("DEBUG: Installing...\n"); // Rousseau: DEBUG
1698 }
1699 else {
1700 if ((Status_Code==STATUS_NOTINSTALLED) | (!Virus_CheckCurrentMBR())) {
1701 // Code not installed, but Config or MBR squashed...
1702 // -> Virus proposed, check for backup (if available)
1703 if (!Option_CID) {
1704 printf("\n\n");
1705 printf("-> ...!ATTENTION!... <-\n");
1706 }
1707 if (Virus_CheckForStealth())
1708 if (!Option_CID) {
1709 printf("Your system GOT infected by a stealth-virus (or your MBR got trashed).\n");
1710 }
1711 else
1712 if (!Option_CID) {
1713 printf("Probably your system was infected by a virus.\n");
1714 printf("Repairing AiR-BOOT will normally squash the virus.\n");
1715 printf("But to be sure it's gone, you should check your harddisc using a virus-scanner.\n");
1716 }
1717
1718 if (!Virus_CheckCurrentMBR()) {
1719 // MBR squashed, so check backup and display message
1720 if (!Option_CID) {
1721 printf("\n");
1722 printf("AiR-BOOT detected that the virus has broken your partition-table.\n");
1723 }
1724 if (Virus_CheckForBackUpMBR()) {
1725 if (!Option_CID) {
1726 printf("Good news: AiR-BOOT has found a (hopefully) functional backup.\n");
1727 printf("Shall I use this backup, instead of the current active one? (Y/N)\n");
1728 }
1729 // User selection, Y/N, if he wants to restore MBR
1730 // *NOT* CID (silent) able
1731 do {
1732 UserKey = getch() | 0x20;
1733 } while (!((UserKey=='y') | (UserKey=='n')));
1734 if (UserKey=='y')
1735 Virus_CopyBackUpMBR();
1736 }
1737 else {
1738 if (!Option_CID) {
1739 printf("Sadly the virus also broke AiR-BOOT's backup. You will have to help yourself.\n");
1740 }
1741 }
1742 }
1743 }
1744 }
1745
1746
1747
1748 // =============================================================
1749 // MAIN-MENU
1750 // =============================================================
1751 if (!Option_CID) {
1752 printf("\n-> ...Please press... <-\n");
1753 }
1754
1755 if (!Option_CID) {
1756 if (Install_IsCorrupt)
1757 printf(" <R> - Repair AiR-BOOT ");
1758 else
1759 if (Status_Code==STATUS_NOTINSTALLED)
1760 printf(" <A> - Add AiR-BOOT ");
1761 else
1762 printf(" <U> - Update/Change AiR-BOOT to ");
1763
1764 printf("'v%x.%1d.%1d/", Bootcode_Version>>8, (Bootcode_Version & 0x0F0)>>4, Bootcode_Version & 0x0F);
1765 Language_PrintF(Bootcode_LanguageID);
1766 printf("' on current system\n");
1767
1768 printf(" <D> - Delete AiR-BOOT from current system\n");
1769 printf(" <Q> - Quit without any change\n");
1770 }
1771
1772
1773
1774 if (Option_Silent || Option_CID) {
1775 // Silent operation? Always add AiR-BOOT then
1776 UserKey = 'a';
1777 }
1778 else {
1779 do {
1780 UserKey = getch() | 0x20;
1781 } while (!((UserKey=='a') || (UserKey=='r') || (UserKey=='u') || (UserKey=='d') || (UserKey=='q')));
1782 }
1783
1784 if (!Option_CID) {
1785 printf("\n\n\n-------------------------------------------------------------------------------\n");
1786 }
1787
1788 switch (UserKey) {
1789 case 'a':
1790 case 'r':
1791 case 'u': {
1792 if (Install_Code || Install_Config) {
1793 if (!Option_CID) {
1794 printf("Add/Repair/Update AiR-BOOT in progress...\n");
1795 }
1796#ifdef PLATFORM_OS2
1797 OS2_GetBootAutoDriveLetter();
1798#endif
1799 if (Install_Code) {
1800 if (!Option_CID) {
1801 printf(" þ Writing AiR-BOOT code...");
1802 }
1803 //~ DumpTrack0();
1804 Install_WriteCode();
1805 //~ DumpTrack0();
1806 if (!Option_CID) {
1807 printf("ok\n");
1808 }
1809 }
1810 if (Install_Config) {
1811 if (!Option_CID) {
1812 printf(" þ Writing AiR-BOOT configuration...");
1813 }
1814 Install_WriteConfig();
1815 if (!Option_CID) {
1816 printf("ok\n");
1817 }
1818 }
1819
1820
1821 if (!Track0Write()) {
1822 if (!Option_CID) {
1823 printf("SAVE ERROR!\n");
1824 }
1825 return 1;
1826 }
1827
1828 if (!Option_CID) {
1829 printf("\n");
1830 printf("Your copy of AiR-BOOT is now fully functional.\n");
1831 if (!Option_Silent) {
1832 printf("Please hit ESC to exit AiR-BOOT installer or ENTER to reboot your system...\n");
1833 }
1834 }
1835 if (Option_Silent || Option_CID) {
1836 // Silent operation? Always reboot system (shall we do this really?)
1837 // No, otherwise installing from MiniLVM will reboot the system
1838 // which is not what the user would expect.
1839 //UserKey = 0x0D;
1840 UserKey = 0x1B;
1841 }
1842 else {
1843 do {
1844 UserKey = getch(); // React on ENTER or ESC
1845 } while (!((UserKey==0x0D) || (UserKey==0x1B)));
1846 }
1847 if (UserKey==0x0D) { // ENTER reboots system... (if not in eCS install mode)
1848
1849 /*
1850 // Rousseau: ## Disable Reboot when installing eComStation ##
1851 // In the install-environment, the MEMDRIVE env-var is defined.
1852 // So, only reboot if this env-var is not defined.
1853 */
1854 if (!getenv("MEMDRIVE")) {
1855 if (!Option_CID) {
1856 printf("Now rebooting system...\n");
1857 }
1858 RebootSystem();
1859 }
1860 ExitOnly = TRUE;
1861 }
1862 }
1863 else {
1864 if (!Option_CID) {
1865 printf(" þ All components of AiR-BOOT are intact and up-to-date. Nothing to do.\n");
1866 }
1867 ExitOnly = TRUE;
1868 }
1869 break;
1870 }
1871 case 'd': {
1872 if (!Option_CID) {
1873 printf(" þ Removing AiR-BOOT automatically is not possible at this time.\n");
1874 }
1875#ifdef PLATFORM_OS2
1876 if (!Option_CID) {
1877 printf(" You may remove AiR-BOOT manually by entering \"FDISK /MBR\" or \"LVM /NEWMBR:1\"\n");
1878 printf(" in commandline.\n");
1879 }
1880#endif
1881#ifdef PLATFORM_WINNT
1882 if (!Option_CID) {
1883 printf(" You may remove AiR-BOOT manually by entering \"FDISK /MBR\" in commandline.\n");
1884 }
1885#endif
1886 ExitOnly = TRUE;
1887 break;
1888 }
1889 default:
1890 break;
1891 }
1892
1893 if (ExitOnly) {
1894 if (!(Option_CID || Option_Silent)) {
1895 printf("\n");
1896 printf("Please hit ENTER to exit AiR-BOOT installer...\n");
1897 while (getch()!=0x0D);
1898 }
1899 }
1900
1901 // Free the buffer memory.
1902 if (Track0) free(Track0);
1903 if (Bootcode) free(Bootcode);
1904
1905 return 0;
1906}
Note: See TracBrowser for help on using the repository browser.