📄 main.c
字号:
dup2(STDOUT, STDIN); /* 2 is /dev/con (stdin) */ dup2(STDOUT, STDERR); /* 4 is /dev/prn */ open("PRN", O_WRONLY); /* Initialize the disk buffer management functions */ /* init_call_init_buffers(); done from CONFIG.C */}STATIC VOID signon(){ printf("\r%S" "Kernel compatibility %d.%d - "#if defined(__BORLANDC__) "BORLANDC"#elif defined(__TURBOC__) "TURBOC"#elif defined(_MSC_VER) "MSC"#elif defined(__WATCOMC__) "WATCOMC"#elif defined(__GNUC__) "GNUC" /* this is hypothetical only */#else#error Unknown compiler generate some bullshit error here, as the compiler should be known#endif#if defined (I386) " - 80386 CPU required"#elif defined (I186) " - 80186 CPU required"#endif#ifdef WITHFAT32 " - FAT32 support"#endif "\n\n%s", MK_FP(FP_SEG(LoL), FP_OFF(LoL->os_release)), MAJOR_RELEASE, MINOR_RELEASE, copyright);}STATIC void kernel(){ CommandTail Cmd; if (master_env[0] == '\0') /* some shells panic on empty master env. */ strcpy(master_env, "PATH=."); fmemcpy(MK_FP(DOS_PSP + 8, 0), master_env, sizeof(master_env)); /* process 0 */ /* Execute command.com from the drive we just booted from */ memset(Cmd.ctBuffer, 0, sizeof(Cmd.ctBuffer)); strcpy(Cmd.ctBuffer, Config.cfgInitTail); for (Cmd.ctCount = 0; Cmd.ctCount < sizeof(Cmd.ctBuffer); Cmd.ctCount++) if (Cmd.ctBuffer[Cmd.ctCount] == '\r') break; /* if stepping CONFIG.SYS (F5/F8), tell COMMAND.COM about it */ /* 3 for string + 2 for "\r\n" */ if (Cmd.ctCount < sizeof(Cmd.ctBuffer) - 5) { char *insertString = NULL; if (singleStep) insertString = " /Y"; /* single step AUTOEXEC */ if (SkipAllConfig) insertString = " /D"; /* disable AUTOEXEC */ if (insertString) { /* insert /D, /Y as first argument */ char *p, *q; for (p = Cmd.ctBuffer; p < &Cmd.ctBuffer[Cmd.ctCount]; p++) { if (*p == ' ' || *p == '\t' || *p == '\r') { for (q = &Cmd.ctBuffer[Cmd.ctCount + 1]; q >= p; q--) q[3] = q[0]; memcpy(p, insertString, 3); break; } } /* save buffer -- on the stack it's fine here */ Config.cfgInitTail = Cmd.ctBuffer; } } init_call_p_0(&Config); /* go execute process 0 (the shell) */}/* check for a block device and update device control block */STATIC VOID update_dcb(struct dhdr FAR * dhp){ REG COUNT Index; COUNT nunits = dhp->dh_name[0]; struct dpb FAR *dpb; if (LoL->nblkdev == 0) dpb = LoL->DPBp; else { for (dpb = LoL->DPBp; (ULONG) dpb->dpb_next != 0xffffffffl; dpb = dpb->dpb_next) ; dpb = dpb->dpb_next = KernelAlloc(nunits * sizeof(struct dpb), 'E', Config.cfgDosDataUmb); } for (Index = 0; Index < nunits; Index++) { dpb->dpb_next = dpb + 1; dpb->dpb_unit = LoL->nblkdev; dpb->dpb_subunit = Index; dpb->dpb_device = dhp; dpb->dpb_flags = M_CHANGED; if ((LoL->CDSp != 0) && (LoL->nblkdev < LoL->lastdrive)) { LoL->CDSp[LoL->nblkdev].cdsDpb = dpb; LoL->CDSp[LoL->nblkdev].cdsFlags = CDSPHYSDRV; } ++dpb; ++LoL->nblkdev; } (dpb - 1)->dpb_next = (void FAR *)0xFFFFFFFFl;}/* If cmdLine is NULL, this is an internal driver */BOOL init_device(struct dhdr FAR * dhp, char *cmdLine, COUNT mode, char FAR **r_top){ request rq; char name[8]; if (cmdLine) { char *p, *q, ch; int i; p = q = cmdLine; for (;;) { ch = *p; if (ch == '\0' || ch == ' ' || ch == '\t') break; p++; if (ch == '\\' || ch == '/' || ch == ':') q = p; /* remember position after path */ } for (i = 0; i < 8; i++) { ch = '\0'; if (p != q && *q != '.') ch = *q++; /* copy name, without extension */ name[i] = ch; } } rq.r_unit = 0; rq.r_status = 0; rq.r_command = C_INIT; rq.r_length = sizeof(request); rq.r_endaddr = *r_top; rq.r_bpbptr = (void FAR *)(cmdLine ? cmdLine : "\n"); rq.r_firstunit = LoL->nblkdev; execrh((request FAR *) & rq, dhp);/* * Added needed Error handle */ if ((rq.r_status & (S_ERROR | S_DONE)) == S_ERROR) return TRUE; if (cmdLine) { /* Don't link in device drivers which do not take up memory */ if (rq.r_endaddr == (BYTE FAR *) dhp) return TRUE; /* Don't link in block device drivers which indicate no units */ if (!(dhp->dh_attr & ATTR_CHAR) && !rq.r_nunits) { rq.r_endaddr = (BYTE FAR *) dhp; return TRUE; } /* Fix for multisegmented device drivers: */ /* If there are multiple device drivers in a single driver file, */ /* only the END ADDRESS returned by the last INIT call should be */ /* the used. It is recommended that all the device drivers in */ /* the file return the same address */ if (FP_OFF(dhp->dh_next) == 0xffff) { KernelAllocPara(FP_SEG(rq.r_endaddr) + (FP_OFF(rq.r_endaddr) + 15)/16 - FP_SEG(dhp), 'D', name, mode); } /* Another fix for multisegmented device drivers: */ /* To help emulate the functionallity experienced with other DOS */ /* operating systems when calling multiple device drivers in a */ /* single driver file, save the end address returned from the */ /* last INIT call which will then be passed as the end address */ /* for the next INIT call. */ *r_top = (char FAR *)rq.r_endaddr; } if (!(dhp->dh_attr & ATTR_CHAR) && (rq.r_nunits != 0)) { dhp->dh_name[0] = rq.r_nunits; update_dcb(dhp); } if (dhp->dh_attr & ATTR_CONIN) LoL->syscon = dhp; else if (dhp->dh_attr & ATTR_CLOCK) LoL->clock = dhp; return FALSE;}STATIC void InitIO(void){ struct dhdr far *device = &LoL->nul_dev; /* Initialize driver chain */ do { init_device(device, NULL, 0, &lpTop); device = device->dh_next; } while (FP_OFF(device) != 0xffff);}/* issue an internal error message */VOID init_fatal(BYTE * err_msg){ printf("\nInternal kernel error - %s\nSystem halted\n", err_msg); for (;;) ;}/* Initialize all printers this should work. IMHO, this might also be done on first use of printer, as I never liked the noise by a resetting printer, and I usually much more often reset my system, then I print :-) */STATIC VOID InitPrinters(VOID){ iregs r; int num_printers, i; init_call_intr(0x11, &r); /* get equipment list */ num_printers = (r.a.x >> 14) & 3; /* bits 15-14 */ for (i = 0; i < num_printers; i++) { r.a.x = 0x0100; /* initialize printer */ r.d.x = i; init_call_intr(0x17, &r); }}STATIC VOID InitSerialPorts(VOID){ iregs r; int serial_ports, i; init_call_intr(0x11, &r); /* get equipment list */ serial_ports = (r.a.x >> 9) & 7; /* bits 11-9 */ for (i = 0; i < serial_ports; i++) { r.a.x = 0xA3; /* initialize serial port to 2400,n,8,1 */ r.d.x = i; init_call_intr(0x14, &r); }}/***************************************************************** if kernel.config.BootHarddiskSeconds is set, the default is to boot from harddisk, because the user is assumed to just have forgotten to remove the floppy/bootable CD from the drive. user has some seconds to hit ANY key to continue to boot from floppy/cd, else the system is booted from HD*/STATIC int EmulatedDriveStatus(int drive,char statusOnly){ iregs r; char buffer[0x13]; buffer[0] = 0x13; r.a.b.h = 0x4b; /* bootable CDROM - get status */ r.a.b.l = statusOnly; r.d.b.l = (char)drive; r.si = (int)buffer; init_call_intr(0x13, &r); if (r.flags & 1) return FALSE; return TRUE; }STATIC void CheckContinueBootFromHarddisk(void){ char *bootedFrom = "Floppy/CD"; iregs r; int key; if (InitKernelConfig.BootHarddiskSeconds == 0) return; if (LoL->BootDrive >= 3) {#if 0 if (!EmulatedDriveStatus(0x80,1))#endif { /* already booted from HD */ return; } } else {#if 0 if (!EmulatedDriveStatus(0x00,1))#endif bootedFrom = "Floppy"; } printf("\n" "\n" "\n" " Hit any key within %d seconds to continue booot from %s\n" " Hit 'H' or wait %d seconds to boot from Harddisk\n", InitKernelConfig.BootHarddiskSeconds, bootedFrom, InitKernelConfig.BootHarddiskSeconds ); key = GetBiosKey(InitKernelConfig.BootHarddiskSeconds); if (key != -1 && (key & 0xff) != 'h' && (key & 0xff) != 'H') { /* user has hit a key, continue to boot from floppy/CD */ printf("\n"); return; } /* reboot from harddisk */ EmulatedDriveStatus(0x00,0); EmulatedDriveStatus(0x80,0); /* now jump and run */ r.a.x = 0x0201; r.c.x = 0x0001; r.d.x = 0x0080; r.b.x = 0x7c00; r.es = 0; init_call_intr(0x13, &r); { void (far *reboot)(void) = (void (far*)(void)) MK_FP(0x0,0x7c00); (*reboot)(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -