📄 ldtmanag.c
字号:
}/* fd32_set_segment_limit - Implementation of DPMI 0.9 service 0008h * "Set Segment Limit" * * This code is based on CWSDPMI 5.0, file exphdlr.c * by Salvo Isaja * * FIX ME: DPMI Specifications indicate the following error codes to return * that are currently not considered (by CWSDPMI too, however): * * 8021h invalid value (CX <> 0 on a 16-bit DPMI host; or the * limit is greater than 1 MB, but the low twelve bits are * not set) * 8025h invalid linear address (changing the limit would cause * the descriptor to reference a linear address range * outside that allowed for DPMI clients.) * * FIX ME: The DPMI Specifications say also that: * A DPMI 1.0 host will reload any segment registers which contain * the selector specified in register BX. It is suggested that * DPMI 0.9 hosts also implement this. */int fd32_set_segment_limit(WORD Selector, DWORD Limit){ WORD i,j,k; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Set Segment Limit: Selector 0x%x Limit 0x%lx\n",Selector,Limit);#endif ErrorCode = sel_to_ldt_index(Selector, &i); if (ErrorCode < 0) { return ErrorCode; } j = (WORD) Limit; k = Limit >> 16; if (k > 0xF) { j = (j >> 12) | (k << 4); k = 0x80 | (k >> 12); } DESCRIPTOR_TABLE(i).lim_lo = j; DESCRIPTOR_TABLE(i).gran &= 0x70; DESCRIPTOR_TABLE(i).gran |= k; return NO_ERROR;}/* fd32_set_descriptor_access_rights - Implementation of DPMI 0.9 service 0009h * "Set Descriptor Access Rights" * * This code is based on CWSDPMI 5.0, file exphdlr.c * by Salvo Isaja * * FIX ME: DPMI Specifications indicate the following error codes to return * that are currently not considered (by CWSDPMI too, however): * * 8021h invalid value (access rights/type bytes invalid) * 8025h invalid linear address (changing the access rights/type * bytes would cause the descriptor to reference a linear * address range outside that allowed for DPMI clients.) * * FIX ME: The DPMI Specifications say also that: * A DPMI 1.0 host will reload any segment registers which contain * the selector specified in register BX. It is suggested that * DPMI 0.9 hosts also implement this. */int fd32_set_descriptor_access_rights(WORD Selector, WORD Rights){ WORD i; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Set Descriptor Access Rights: Selector 0x%x Rights 0x%x\n", Selector, Rights);#endif ErrorCode = sel_to_ldt_index(Selector,&i); if (ErrorCode < 0) { return ErrorCode; } DESCRIPTOR_TABLE(i).access = 0x10 | (BYTE) Rights; DESCRIPTOR_TABLE(i).gran = (0x0F & DESCRIPTOR_TABLE(i).gran) | ((Rights >> 8) & 0xD0); return NO_ERROR;}/* fd32_create_alias_descriptor - Implementation of DPMI 0.9 service 000Ah * "Create Alias Descriptor" * * This code is based on CWSDPMI 5.0, file exphdlr.c * by Salvo Isaja */int fd32_create_alias_descriptor(WORD Selector){ WORD Source, Dest, new_selector; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Create Alias Descriptor: Selector 0x%x\n", Selector);#endif ErrorCode = sel_to_ldt_index(Selector, &Source); if (ErrorCode < 0) return ErrorCode; ErrorCode = fd32_allocate_descriptors(1); if (ErrorCode < 0) return ErrorCode; Dest = ErrorCode; /* We can safely ignore the exit code of the following */ sel_to_ldt_index(Dest,&Dest); new_selector = INDEX_TO_SELECTOR(Dest); DESCRIPTOR_TABLE(Dest) = DESCRIPTOR_TABLE(Source); /* Data, exp-up, wrt */ DESCRIPTOR_TABLE(Dest).access = 2 | (DESCRIPTOR_TABLE(Dest).access & 0xF0); return new_selector;}/* fd32_get_descriptor - Implementation of DPMI 0.9 service 000Bh * "Get Descriptor" * * FIX ME: CWSDPMI performs a check on the address of the destination * buffer that I've ignored for simplicity. * CWSDPMI also performs a more complicated copy process that * is still unknown to me. * * This code is based on CWSDPMI 5.0, file exphdlr.c * by Salvo Isaja */int fd32_get_descriptor(WORD Selector, WORD BufferSelector, DWORD BufferOffset){ WORD i; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Get Descriptor: Selector 0x%x Buffer: 0x%x:0x%lx\n", Selector, BufferSelector, BufferOffset);#endif /* TO DO: CHECK_POINTER(tss_ptr->tss_es, tss_ptr->tss_edi); */ ErrorCode = sel_to_ldt_index(Selector, &i); if (ErrorCode < 0) return ErrorCode; /* The following assembly code copies the descriptor into */ /* the buffer pointed by the specified 48-bit pointer. */ asm("push %%es \n" "mov %%ax,%%es \n" "mov (%%ebx),%%edx \n" "mov %%edx,%%es:(%%edi) \n" "mov 4(%%ebx),%%edx \n" "mov %%edx,%%es:4(%%edi)\n" "pop %%es \n" : : "b" (&DESCRIPTOR_TABLE(i)), "a" (BufferSelector), "D" (BufferOffset) : "edx"); return NO_ERROR;}/* fd32_set_descriptor - Implementation of DPMI 0.9 service 000Ch * "Set Descriptor" * * FIX ME: CWSDPMI performs a check on the address of the destination * buffer that I've ignored for simplicity. * CWSDPMI also performs a more complicated copy process that * is still unknown to me. * * FIX ME: DPMI Specifications indicate the following error codes to return * that are currently not considered (by CWSDPMI too, however): * * 8021h invalid value (access rights/type bytes invalid) * 8025h invalid linear address (descriptor references a linear * address range outside that allowed for DPMI clients) * * FIX ME: The DPMI Specifications say also that: * "If the descriptor's present bit is not set, then the only error * checking is that the client's CPL must be equal to the * descriptor's DPL field and the "must be 1" bit in the descriptor's * byte 5 must be set." * This check is currently not performed by FD32 nor by CWSDPMI. * * FIX ME: The DPMI Specifications say also that: * A DPMI 1.0 host will reload any segment registers which contain * the selector specified in register BX. It is suggested that * DPMI 0.9 hosts also implement this. * * This code is based on CWSDPMI 5.0, file exphdlr.c * by Salvo Isaja */int fd32_set_descriptor(WORD Selector, WORD BufferSelector, DWORD BufferOffset){ WORD i; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Set Descriptor: Selector 0x%x Buffer: 0x%x:0x%lx\n", Selector, BufferSelector, BufferOffset);#endif /* TO DO: CHECK_POINTER(tss_ptr->tss_es, tss_ptr->tss_edi); */ ErrorCode = sel_to_ldt_index(Selector, &i); if (ErrorCode < 0) return ErrorCode; /* The following assembly code copies the buffer pointed */ /* by the specified 48-bit pointer into the descriptor. */ asm("push %%es \n" "mov %%ax,%%es \n" "mov %%es:(%%ebx),%%edx \n" "mov %%edx,(%%edi) \n" "mov %%es:4(%%ebx),%%edx\n" "mov %%edx,4(%%edi) \n" "pop %%es \n" : : "D" (&DESCRIPTOR_TABLE(i)), "a" (BufferSelector), "b" (BufferOffset) : "edx"); DESCRIPTOR_TABLE(i).access |= 0x10; /* Make sure non-system, non-zero */ return NO_ERROR;}/* fd32_get_multiple_descriptors - Implementation of DPMI 1.0 service 000Eh * "Get Multiple Descriptors" * by Salvo Isaja */int fd32_get_multiple_descriptors(WORD Descriptors, WORD BufferSelector, DWORD BufferOffset){ WORD i; WORD Selector; int Count; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Get Multiple Descriptor: Descriptors: 0x%x Buffer: 0x%x:0x%lx\n", Descriptors, BufferSelector, BufferOffset);#endif /* TO DO: CHECK_POINTER(tss_ptr->tss_es, tss_ptr->tss_edi); */ asm("push %%fs \n" "mov %%ax,%%fs\n" : : "a" (BufferSelector)); for (Count = 0; Count < Descriptors; Count++) { asm("mov %%fs:(%%edi),%%ax" : "=a" (Selector) : "D" (BufferOffset)); ErrorCode = sel_to_ldt_index(Selector, &i); if (ErrorCode < 0) return ErrorCode; /* FIX ME: Should return Count */ asm("mov (%%ebx),%%eax \n" "mov %%eax,%%fs:2(%%edi)\n" "mov 4(%%ebx),%%eax \n" "mov %%eax,%%fs:6(%%edi)\n" : : "b" (&DESCRIPTOR_TABLE(i)), "D" (BufferOffset) : "eax"); BufferOffset += 10; } asm("pop %fs"); return NO_ERROR;}/* fd32_set_multiple_descriptors - Implementation of DPMI 1.0 service 000Fh * "Set Multiple Descriptors" * by Salvo Isaja * * FIX ME: DPMI Specifications indicate the following error codes to return * that are currently not considered: * * 8021h invalid value (access rights/type bytes invalid) * 8025h invalid linear address (descriptor references a linear * address range outside that allowed for DPMI clients) * * FIX ME: The DPMI Specifications say also that: * "If the descriptor's present bit is not set, then the only error * checking is that the client's CPL must be equal to the * descriptor's DPL field and the "must be 1" bit in the descriptor's * byte 5 must be set." * This check is currently not performed. * * FIX ME: The DPMI Specifications say also that: * A DPMI 1.0 host will reload any segment registers which contain * the selector specified in register BX. It is suggested that * DPMI 0.9 hosts also implement this. */int fd32_set_multiple_descriptors(WORD Descriptors, WORD BufferSelector, DWORD BufferOffset){ WORD i; WORD Selector; int Count; int ErrorCode;#ifdef __DEBUG__ fd32_log_printf("[DPMI] Set Multiple Descriptor: Descriptors: 0x%x Buffer: 0x%x:0x%lx\n", Descriptors, BufferSelector, BufferOffset);#endif /* TO DO: CHECK_POINTER(tss_ptr->tss_es, tss_ptr->tss_edi); */ asm("push %%fs \n" "mov %%ax,%%fs\n" : : "a" (BufferSelector)); for (Count = 0; Count < Descriptors; Count++) { asm("mov %%fs:(%%ebx),%%ax" : "=a" (Selector) : "b" (BufferOffset)); ErrorCode = sel_to_ldt_index(Selector, &i); if (ErrorCode < 0) return ErrorCode; /* FIX ME: Should return Count */ asm("mov %%fs:2(%%ebx),%%eax\n" "mov %%eax,(%%edi) \n" "mov %%fs:6(%%ebx),%%eax\n" "mov %%eax,4(%%edi) \n" : : "b" (BufferOffset), "D" (&DESCRIPTOR_TABLE(i)) : "eax"); BufferOffset += 10; DESCRIPTOR_TABLE(i).access |= 0x10; /* Make sure non-system, non-zero */ } asm("pop %fs"); return NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -