📄 kernel.hhf
字号:
#if( !@defined( kernel_hhf ))?kernel_hhf := true;#includeonce( "os/fs.hhf" )// kdebug is outside any namespace because we're going// to use it fairly often.// Ditto for kassert (text constant) and KDEBUG.#if( @defined( __kernel__ )) // The following disables debugging code by default // (KNDEBUG = true prevents emission of debug code). // Note that "boolean(1)" is another way of saying // "true" except it doesn't require true to be // defined. ?KNDEBUG : boolean := boolean(1); //true #macro kdebug( instrs ); #if( !KNDEBUG ) pushad(); pushfd(); instrs; popfd(); popad(); #endif #endmacro; const kassert :text := "?linux.kassertLN := @linenumber; " "?linux.kassertFN := @filename; " "linux.kassert"; // The following kernel constants also exist outside the // linux namespace because they get used so often it's too // much of a pain to always type "linux." as a prefix to them: kern_emerg :text := """<0>"""; // system is unusable kern_alert :text := """<1>"""; // action must be take immediately kern_crit :text := """<2>"""; // critical conditions kern_err :text := """<3>"""; // error conditions kern_warning :text := """<4>"""; // warning conditions kern_notice :text := """<5>"""; // normal, but significant condition kern_info :text := """<6>"""; // informational kern_debug :text := """<6>"""; // debug-level messages namespace linux; @fast; val kassertLN: dword; kassertFN: string; #macro kassert( expr ):skipCode,msg,fn,ln; #if( !KNDEBUG ) readonly msg :string := @string:expr; fn :string := linux.kassertFN; ln :dword := linux.kassertLN; endreadonly; pushfd(); jt( expr ) skipCode; pushad(); linux.printk ( "Kernel assertion failed: '%s' (line:%d, file: %s)\n", msg, ln, fn ); popad(); // We can't really abort the kernel, so just keep going! skipCode: popfd(); #endif #endmacro;end linux;#endifnamespace linux; @fast;type sysinfo_t: record uptime :int32; loads :uns32[3]; totalram :uns32; freeram :uns32; shardram :uns32; bufferram :uns32; totalswap :uns32; freeswap :uns32; procs :uns16; align(4); totalhigh :dword; freehigh :dword; mem_unit :dword; align(64); endrecord;#if( @defined( __kernel__ )) // Only allow kernel-module access to the following symbols. // Constants, types, and macros related to the // major and minor device numbers: const minorbits := 8; minormask := ((1 << minorbits) - 1); val kdev_t_name :kdev_t; // These macros are ugly because I decided to stick // lots of type checking and optimization into them. // major(dev) - extracts a major device number // from dev object (which should be a kdev_t object). // // Returns a constant if dev is a constant, otherwise // returns the major number in EAX. // // Accepts: unsigned constants, two and four byte registers, // and memory objects whose type is kdev_t (or whatever // kdev_t's base type is, "word" currently). // // Note that this macro fully knows that kdev_t is currently // a word and must be rewritten if (when) kdev_t changes to // some other type. // // Note that the major number is currently the H.O. byte // of the kdev_t object, but there are plans to change this // by Linux v2.6. #macro major(dev):rtns; returns ( { #if( @isconst( dev )) // If "dev" is a constant, just assume it's // an integer (rely upon HLA to catch non-int // consts) and return the constant as this // macro's RETURNS value. If this macro were // consistent, I'd return the value in EAX. // However, by returning a constant if it // gets passed a constant, we can invoke // this macro in a constant expression. ?rtns :string := string( dev >> linux.minorbits ); #elseif( @isreg(dev) ) // It's a register. Allow 16-bit and 32-bit // registers (assume they contain legitimate // kdev_t values). #if( @size( dev ) = 2 ) // Do some optimization if it's // AX, BX, CX, or DX: #if( @lowercase( @string:dev, 0 ) = "ax" ) movzx( ah, eax ); #elseif( @lowercase( @string:dev, 0 ) = "bx" ) movzx( bh, eax ); #elseif( @lowercase( @string:dev, 0 ) = "cx" ) movzx( ch, eax ); #elseif( @lowercase( @string:dev, 0 ) = "dx" ) movzx( dh, eax ); #else // If it's SI, DI, BP, or SP, do // this the hard way: movzx( dev, eax ); shr( linux.minorbits, eax ); #endif #elseif( @size( dev ) = 4 ) // Do some optimization if it's // EAX, EBX, ECX, or EDX: #if( @lowercase( @string:dev, 0 ) = "eax" ) movzx( ah, eax ); #elseif( @lowercase( @string:dev, 0 ) = "ebx" ) movzx( bh, eax ); #elseif( @lowercase( @string:dev, 0 ) = "ecx" ) movzx( ch, eax ); #elseif( @lowercase( @string:dev, 0 ) = "edx" ) movzx( dh, eax ); #else mov( dev, eax ); shr( linux.minorbits, eax ); #endif #endif ?rtns := "eax"; #elseif ( @typename(dev) = @typename(linux.kdev_t_name) | @typename(dev) = "kdev_t" ) // If it's a valid memory location, then just // extract the H.O. byte: movzx( (type byte dev[1]), eax ); ?rtns := "eax"; #else #error ( "Expected a kdev_t argument, found: " + @typename( dev ) ) ?rtns := ""; #endif }, rtns ) #endmacro; // minor(dev) - extracts a minor device number // from dev object (which should be a kdev_t object). // // Returns a constant if dev is a constant, otherwise // returns the major number in EAX. // // Accepts: unsigned constants, two and four byte registers, // and memory objects whose type is kdev_t (or whatever // kdev_t's base type is, "word" currently). // // Note that this macro fully knows that kdev_t is currently // a word and must be rewritten if (when) kdev_t changes to // some other type. // // Note that the minor number is currently the L.O. byte // of the kdev_t object, but there are plans to change this // by Linux v2.6. #macro minor(dev):rtns; returns ( { #if( @isconst( dev )) // If "dev" is a constant, just assume it's // an integer (rely upon HLA to catch non-int // consts) and return the constant as this // macro's RETURNS value. If this macro were // consistent, I'd return the value in EAX. // However, by returning a constant if it // gets passed a constant, we can invoke // this macro in a constant expression. ?rtns :string := string( dev & linux.minormask ); #elseif( @isreg(dev) ) // It's a register. Allow 16-bit and 32-bit // registers (assume they contain legitimate // kdev_t values). #if( @size( dev ) = 2 ) // Do some optimization if it's // AX, BX, CX, or DX: #if( @lowercase( @string:dev, 0 ) = "ax" ) movzx( al, eax ); #elseif( @lowercase( @string:dev, 0 ) = "bx" ) movzx( bl, eax ); #elseif( @lowercase( @string:dev, 0 ) = "cx" ) movzx( cl, eax ); #elseif( @lowercase( @string:dev, 0 ) = "dx" ) movzx( dl, eax ); #else // If it's SI, DI, BP, or SP, do // this the hard way: movzx( dev, eax ); and( linux.minormask, eax ); #endif #elseif( @size( dev ) = 4 ) // Do some optimization if it's // EAX, EBX, ECX, or EDX: #if( @lowercase( @string:dev, 0 ) = "eax" ) movzx( al, eax ); #elseif( @lowercase( @string:dev, 0 ) = "ebx" ) movzx( bl, eax ); #elseif( @lowercase( @string:dev, 0 ) = "ecx" ) movzx( cl, eax ); #elseif( @lowercase( @string:dev, 0 ) = "edx" ) movzx( dl, eax ); #else mov( dev, eax ); and( linux.minormask, eax ); #endif #endif ?rtns := "eax"; #elseif ( @typename(dev) = @typename(linux.kdev_t_name) | @typename(dev) = "kdev_t" ) // If it's a valid memory location, then just // extract the L.O. byte: movzx( (type byte dev), eax ); ?rtns := "eax"; #else #error ( "Expected a kdev_t argument, found: " + @typename( dev ) ) ?rtns := ""; #endif }, rtns ) #endmacro; // mkdev(ma,mi) // // Creates a kdev_t value from the major (ma) and minor (mi) // values supplied as arguments. If both arguments are constants, // then this macro returns a constant operand. If either or both // arguments are not constants, then this function returns the // kdev_t value in EAX (AX contains the value which is zero- // extended into EAX). // // This macro fully knows about kdev_t's internal format // and must be rewritten if (when) kdev_t's internal representation // changes. #macro mkdev(ma,mi):rtns, a, az, i, iz; returns ( { #if( @isconst( ma ) & @isconst( mi )) ?rtns:string := string( (ma << 8) | mi ); #else ?a := @lowercase( @string:ma, 0 ); ?az := @size( ma ); ?i := @lowercase( @string:mi, 0 ); ?iz := @size( mi ); #if( az <> iz ) #error( "mkdev operands must be the same size" ) ?rtns := "0"; #elseif( az=1 ) // iz is also 1 #if( a = "al" & i = "ah" ) xchg( al, ah ); and( $FFFF, eax ); #elseif( a = "ah" & i = "al" ) and( $FFFF, eax ); #elseif( a = "ah" ) mov( mi, al ); and( $FFFF, eax ); #elseif( a = "al" ) mov( al, ah ); mov( mi, al ); and( $FFFF, eax ); #elseif( i = "al" ) mov( ma, ah ); and( $FFFF, eax ); #elseif( i = "ah" ) mov( ah, al ); mov( ma, ah ); and( $FFFF, eax ); #else movzx( mi, eax ); mov( ma, ah ); #endif; #elseif( az=2 ) // iz is also 2 #if( a = "ax" ) // We'll just have to assume // that mi is in the range 0..255: mov( al, ah ); or( mi, ax ); and( $FFFF, eax ); #elseif( i = "ax" ) // We'll just have to assume // that ma is in the range 0..255: mov( al, ah ); or( ma, ax ); xchg( al, ah ); and( $FFFF, eax ); #elseif( @isreg( ma ) ) // ma is register, who knows // what mi is? mov( ma, ax ); mov( al, ah ); or( mi, ax ); and( $FFFF, eax ); #elseif( @isreg( mi ) ) // ma is memory, mi is register: mov( (type byte ma), ah ); or( mi, ax ); and( $FFFF, eax ); #else // Assume they're both memory: movzx( (type byte mi), eax ); mov( (type byte ma), ah ); #endif #elseif( az=4 ) // iz is also 4 #if( a = "eax" ) // We'll just have to assume // that mi is in the range 0..255: mov( al, ah ); or( mi, eax ); and( $FFFF, eax ); #elseif( i = "eax" ) // We'll just have to assume // that ma is in the range 0..255: mov( al, ah ); or( ma, eax ); xchg( al, ah ); and( $FFFF, eax ); #elseif( @isreg( ma ) ) // ma is register, who knows // what mi is? mov( ma, eax ); mov( al, ah ); or( mi, eax ); and( $FFFF, eax ); #elseif( @isreg( mi ) ) // ma is memory, mi is register: mov( (type byte ma), ah ); or( mi, eax ); and( $FFFF, eax ); #else // Assume they're both memory: movzx( (type byte mi), eax ); mov( (type byte ma), ah ); #endif #endif ?rtns := "eax"; #endif }, rtns ) #endmacro; // kdev_t_to_nr( kdt ) // // Translates a kdev_t object (currently a word) // to a dword object in EAX. #macro kdev_t_to_nr(dev); returns ( { #if ( @typename(dev) <> @typename( linux.kdev_t_name ) ) #error ( "kdev_t_to_nr argument must be of type kdev_t" ) #else movzx( dev, eax ); #endif; },"eax" ) #endmacro; // to_kdev_t(dev)- // // Translates a dword object to a kdev_t object in AX. #macro to_kdev_t(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -