# osimplay extensions for creating segment descriptors (data) in a GDT. 


		# special descriptor type-numbers in decimal
LDT=2	
CallGate=4 
TaskGate=5		
InterruptGate16=6 	
TrapGate16=7 
CallGate32=12 		
InterruptGate32=14	
TrapGate32=15
AvailableTSS32=9 	
BusyTSS32=11
AvailableTSS16=1	
BusyTSS16=3 	


mddefaults () {   # set defaults to ring0 code

	mdtype= 		# assert for special types only
	mdexecutable=1		# apparently there's a typo in 
				# 386intel.txt. Bit 3 of byte 6 
				# differentiates data and code segments.
	mdlimit=0xfffff 		
	mdlimitshifted=1	# Granularity, 1 or 4k, 4k default
	mdbase=0 	
	mdnon0based=0		# expanddown, same bit pos. as Conforming
	mdinheritperms=0 	# Conforming, same bit pos. as expanddown
	mdDPL=0
	mdreadcode=0 		# RW bit	OR these two in builder
	mdwritedata=1 		# RW bit
	mdpresent=1
	mdUSE32=1		# Default Bit    - same bit
	mdstack32=1		# Big           /
 }



mdinstantiate () { #
	ad  $mdlimit
	mdlimit=$((mdlimit>>16))

	ad  $mdbase
	mdbase=$((mdbase>>16))
	ab  $mdbase			# 5 easy ones in the bin
	mdbase=$((mdbase>>8))	
					# fold together the twofers
	mdRW=$((mdreadcode|mdwritedata))
	mdCZ=$((mdnon0based|mdinheritperms))
	mdBO=$((mdUSE32&mdstack32))

	mdlospec=$((mdpresent<<2))
	mdlospec=$((mdlospec|mdDPL))
	mdlospec=$((mdlospec<<1))		# make room for issegment
	if test "$mdtype"  ; then
		mdlospec=$((mdlospec<<4))	# skip issegment	
		mdlospec=$((mdlospec|mdtype))
	else
		mdlospec=$((mdlospec|1))
		mdlospec=$((mdlospec<<1))
		mdlospec=$((mdlospec|mdexecutable))
		mdlospec=$((mdlospec<<1))
		mdlospec=$((mdlospec|mdCZ))
		mdlospec=$((mdlospec<<1))
		mdlospec=$((mdlospec|mdRW))
		mdlospec=$((mdlospec<<1))
	fi
	ab $mdlospec				# 6 down, two to go

	mdhispec=$((mdlimitshifted<<1))
	mdhispec=$((mdhispec|mdBO))
	
	mdhispec=$((mdhispec<<6))
	mdhispec=$((mdhispec|mdlimit))		
	ab $mdhispec

	ab $mdbase

}

echo "

bit-resolution 386 segment/gate descriptor layout

per pmode GDT/IDT/LDT descriptor, 8 bytes each...

bit	byte

7	0	low-significance dual of limit
6	0	.	
5	0	.
4	0	.
3	0	.
2	0	.
1	0	.
0	0	.
		.
7	1	.
6	1	.
5	1	.
4	1	.
3	1	.
2	1	.
1	1	.
0	1	.............................

7	2	bytes 0, 1 & 2 of base
6	2	.
5	2	.
4	2	.
3	2	.
2	2	.
1	2	.
0	2	.
                .
7	3	.
6	3	.
5	3	.
4	3	.
3	3	.
2	3	.
1	3	.
0	3	.
		.
7	4	.
6	4	.
5	4	.
4	4	.
3	4	.
2	4	.
1	4	.
0	4	............................


mdlospec byte
7	5	present		system variable, default to 1

6	5	DPL		msb of 2-bit Descriptor Priviledge Level	
5	5	dpl		lsb descriptor priviledge level

4	5	segment		1=DS/CS segment, 0=gate/TSS etc.

3	5	special type  	or
		EXECUTABLE SEGMENT=1 (386INTEL.TXT is wrong, or mine 
					is bent. Table 6-1 I think.)	

		expandup|conforming
2	5	special type	data zerobased=0, base=limit =1
				code conforming-permissions
1	5	special type	Read/write

0	5	segment-accessed (system variable) or low bit of gate type


mdhispec byte
		grainy
7	6	granularity of limit, 0=1, 1=4k

6	6	big stack data, NOT-default codesize code
5	6	0
4	6	available to system designers, guaranteed x86 don't-care

3	6	msnybble of limit
2	6	msnybble of limit
1	6 	msnybble of limit
0	6	msnybble of limit


7	7	byte 3 of base
6	7	.
5	7	.
4	7	.
3	7	.
2	7	.
1	7	.
0	7	........................



         DESCRIPTORS USED FOR APPLICATIONS CODE AND DATA SEGMENTS

  31                23                15                7               0
 -------------------------------------------------------------------------
 -                 - - - -A-         - -     - -     - -                 -
 -   BASE 31..24   -G-X-O-V- LIMIT   -P- DPL -1- TYPE-A-  BASE 23..16    - 4
 -                 - - - -L- 19..16  - -     - -     - -                 -
 -------------------------------------------------------------------------
 -                                   -                                   -
 -        SEGMENT BASE 15..0         -       SEGMENT LIMIT 15..0         - 0
 -                                   -                                   -
 -------------------------------------------------------------------------

                DESCRIPTORS USED FOR SPECIAL SYSTEM SEGMENTS

  31                23                15                7               0
 -------------------------------------------------------------------------
 -                 - - - -A-         - -     - -       -                 -
 -   BASE 31..24   -G-X-O-V- LIMIT   -P- DPL -0-  TYPE -  BASE 23..16    - 4
 -                 - - - -L- 19..16  - -     - -       -                 -
 -------------------------------------------------------------------------
 -                                   -                                   -
 -        SEGMENT BASE 15..0         -       SEGMENT LIMIT 15..0         - 0
 -                                   -                                   -
 -------------------------------------------------------------------------

           A      - ACCESSED
           AVL    - AVAILABLE FOR USE BY SYSTEMS PROGRAMMERS
           DPL    - DESCRIPTOR PRIVILEGE LEVEL
           G      - GRANULARITY
           P      - SEGMENT PRESENT
.........................................................


INTeL
senses of some flags
      -  Limit = 64K   (FFFFH)
      -  Byte granular (G = 0)
      -  Expand up     (E = 0)
      -  Writable      (W = 1)
      -  Present       (P = 1)

The limit field of a segment descriptor is used by the processor to prevent
programs from addressing outside the segment. The processor's interpretation
of the limit depends on the setting of the G (granularity) bit. For data
segments, the processor's interpretation of the limit depends also on the
E-bit (expansion-direction bit) and the B-bit (big bit) (refer to Table
6-2).

When G=0, the actual limit is the value of the 20-bit limit field as it
appears in the descriptor. In this case, the limit may range from 0 to
0FFFFFH (2^(20) - 1 or 1 megabyte). When G=1, the processor appends 12
low-order one-bits to the value in the limit field. In this case the actual
limit may range from 0FFFH (2^(12) - 1 or 4 kilobytes) to 0FFFFFFFFH(2^(32)
- 1 or 4 gigabytes).

For all types of segments except expand-down data segments, the value of
the limit is one less than the size (expressed in bytes) of the segment. The
processor causes a general-protection exception in any of these cases:

  -  Attempt to access a memory byte at an address > limit.
  -  Attempt to access a memory word at an address -limit.
  -  Attempt to access a memory doubleword at an address -(limit-2).

For expand-down data segments, the limit has the same function but is
interpreted differently. In these cases the range of valid addresses is from
limit + 1 to either 64K or 2^(32) - 1 (4 Gbytes) depending on the B-bit. An
expand-down segment has maximum size when the limit is zero.

The expand-down feature makes it possible to expand the size of a stack by
copying it to a larger segment without needing also to update intrastack
pointers.

Table 6-2. Useful Combinations of E, G, and B Bits


Case:                    1         2         3         4

Expansion Direction      U         U         D         D
G-bit                    0         1         0         1
B-bit                    X         X         0         1

Lower bound is:
     0                   X         X
     LIMIT+1                                 X
shl(LIMIT,12,1)+1                                      X

Upper bound is:
     LIMIT               X
     shl(LIMIT,12,1)               X
     64K-1                                   X
     4G-1                                              X

Max seg size is:
     64K                 X
     64K-1                         X
     4G-4K                                   X
     4G                                                X

Min seg size is:
     0                   X         X
     4K                                      X         X



" > /dev/null

# true=1. 

echo "

Compemble 386 segment descriptor init values to binary file. Keep a table
index count. Extends shasm/osimplay and works here with... GNU bash,
version 2.02.0(1)-release (i486-pc-linux-gnulibc1) Copyright 1998 Free
Software Foundation, Inc. Trailing commentary is about half from
386INTEL.TXT

No bounds-checking of your inputs supplied. Things that are too big get
ORed into the wrong fields.

Do the mddefault routine, do the mdinstantiate, and you should get a
descriptor like a Linux KERNEL_CS seg. This is how I found out there's a
typo in 386INTEL in chart 6-1 or so. Then change things between mddefault
and mdinstantiate for successive descriptors. The gate types haven't been
checked because I haven't needed them yet.

Rick Hohensee
Precision Mojo Engineer


" >> /dev/null


