Dienstag, 22. Mai 2012

yab - den Typ einer Partition ermitteln

Aufbauend auf meine letzten beiden Beiträge "yab - den Inhalt der Partitions- Tabelle ermitteln..." und "yab - Anzahl der Partitionen ermitteln", möchte ich Euch heute zeigen, was wir mit den, aus dem Boot- Sektor, gewonnenen Daten noch so anstellen können.

Bereits beim Zählen der Partitionen habe ich das jeweils 5. Byte, des jeweils 16 Byte großen Eintrages, verwendet. Ist dieses ungleich Null, ist eine Partition vorhanden. Die untenstehende Sub- Routine greift ebenfalls auf dieses Byte zu und wertet es anhand einer Tabelle ("switch / case") aus.

 Natürlich habe ich mir diese Tabelle nicht selbst ausgedacht, sie entspricht vielmehr der aktuellen Liste der "TU Eindhoven" welche Ihr hier einsehen könnt.

http://www.win.tue.nl/~aeb/partitions/partition_types-1.html

Zur Erklärung des Quell- Textes gibt es wie üblich nicht viel zu sagen, entsprechende Kommentare sind reichlich vorhanden. Allerdings habe ich lange überlegt den Quelltext anzuzeigen, da dieser sehr lang ist. Die teilweise etwas ungewöhnliche Notation ist lediglich der Anzeige geschuldet, da die Länge der einzelnen Zeilen sonst die Anzeige "gesprengt" hätte. Der Quelltext läßt sich dadurch erheblich verkürzen, indem man die einzelnen Zeilen wie folgt zusammenfaßt.

Anstelle von ...

case 8:
  PType$ = "OS/2 (v1.0-1.3 only) / AIX boot partition / SplitDrive / "
  PType$ = PType$ + "Commodore DOS / DELL partition spanning multiple "
  PType$ = PType$ + "drives / QNX 1.x and 2.x ('qny')"
  break

... könnte man auch

case 8: PType$ = "OS/2 (v1.0-1.3 only) / AIX boot partition / SplitDrive / Commodore DOS / DELL partition spanning multiple drives / QNX 1.x and 2.x ('qny')": break

schreiben. Somit würde sich der Quelltext, um eine nicht unerhebliche Zahl von Zeilen, verkürzen.

Der Aufruf der Sub- Routine erfolgt wieder in bekannter Manier, z.B. so. Benötigt wird, wie im Beispiel- Quelltext zu sehen ist, die Sub- Routine "GetPartitionTable" um den Inhalt des Boor- Sektors zu ermitteln. Als zweiter Parameter ist noch die Nummer der entsprechenden Partition anzugeben (gezählt wird hierbei ab 1).


import GetPartitionTable
import GetPartitionType

PT$ = _GetPartitionTable$("/dev/disk/ata/0/master/raw")

print "Type: ", _GetPartitionType$(PT$, 1)


Und hier nun noch der Quelltext in voller Länge.


export sub _GetPartitionType$(PartitionTable$, PartitionNumber)

  // lokale Variablen Definition
  local NumberOfTokens
  local i
  local PType$

  PartitionCount = 0 
        
  // nimmt die einzelnenen Hex- Werte aus dem PartitionTable$ auf
  dim PTable$(1)
  
  // nimmt die einzelnen Dezimal- Werte aus PTable$() auf
  dim PTable(64)
  
  // den PartitionTable- String wieder auftrennen und die Hex- Werte
  // in PTable$ speichern
  NumberOfTokens = split(PartitionTable$, PTable$(), chr$(124))

  // die gespeicherten Hex- Werte wieder in Dezimal- Werte umwandeln
  for i = 1 to NumberOfTokens - 1
  
    PTable(i) = dec(PTable$(i))
  
  next i

  // Position für den richtigen Wert berechnen
  PartitionType = PTable(5 + (PartitionNumber - 1) * 16)

  // Den entsprechenden Partitions- Typ zuweisen.
  // Die Angaben entsprechen der aktuellen Liste der
  // TU Eindhoven
  switch PartitionType
  
    case 0:
      PType$ = "empty"
      break
    case 1:
      PType$ = "DOS 12- bit FAT"
      break
    case 2:
      PType$ = "XENIX root"
      break
    case 3:
      PType$ = "XENIX /usr"
      break
    case 4:
      PType$ = "DOS 3.0+ 16- bit FAT (up to 32M)"
      break
    case 5:
      PType$ = "DOS 3.3+ Extended Partition"
      break
    case 6:
      PType$ = "DOS 3.31+ 16- bit FAT (over 32M)"
      break
    case 7:
      PType$ = "OS/2 IFS (HPFS) / Windows NT NTFS / exFAT / Advanced Linux"
      PType$ = PType$ +" / QNX 2.x pre- 1988"
      break
    case 8:
      PType$ = "OS/2 (v1.0-1.3 only) / AIX boot partition / SplitDrive / "
      PType$ = PType$ + "Commodore DOS / DELL partition spanning multiple "
      PType$ = PType$ + "drives / QNX 1.x and 2.x ('qny')"
      break
    case 9:
      PType$ = "AIX data partition / Coherent filesystem / QNX 1.x and "
      PType$ = PType$ + "2.x ('qnz')"
      break
    case 10:
      PType$ = "OS/2 Boot Manager / Coherent swap partition / OPUS"
      break
    case 11:
      PType$ = "WIN95 OSR2 FAT32"
      break
    case 12:
      PType$ = "WIN95 OSR FAT32, LBA- mapped"
      break
    case 13:
      PType$ = "unused"
      break
    case 14:
      PType$ = "WIN95 DOS 16- bit FAT, LBA- mapped"
      break
    case 15:
      PType$ = "WIN95 extended partition, LBA- mapped"
      break
    case 16:
      PType$ = "OPUS"
      break
    case 17:
      PType$ = "Hidden DOS 12- bit FAT / Leading Edge DOS 3.x logically "
      PType$ = PType$ + "sectored FAT"
      break
    case 18:
      PType$ = "Configuration/diagnostic partition"
      break
    case 19:
      PType$ = "unused"
      break
    case 20:
      PType$ = "Hidden DOS 16- bit FAT < 32M / AST DOS with logically "
      PType$ = PType$ + "sectored FAT"
      break
    case 21:
      PType$ = "unused"
      break
    case 22:
      PType$ = "Hidden DOS 16- bit FAT >= 32M"
      break
    case 23:
      PType$ = "Hidden IFS (HPFS)"
      break
    case 24:
      PType$ = "AST SmartSleep Partition"
      break
    case 25:
      PType$ = "unused"
      break
    case 26:
      PType$ = "unused"
      break
    case 27:
      PType$ = "Hidden WIN95 OSR2 FAT32"
      break
    case 28:
      PType$ = "Hidden WIN95 OSR2 FAT32, LBA- mapped"
      break
    case 29:
      PType$ = "unused"
      break
    case 30:
      PType$ = "Hidden WIN95 16- bit FAT, LBA- mapped"
      break
    case 31:
      PType$ = "unused"
      break
    case 32:
      PType$ = "unused"
      break
    case 33:
      PType$ = "reserved"
      break
    case 34:
      PType$ = "unused"
      break
    case 35:
      PType$ = "reserved"
      break
    case 36:
      PType$ = "NEC DOS 3.x"
      break
    case 37:
      PType$ = "unused"
      break
    case 38:
      PType$ = "reserved"
      break
    case 39:
      PType$ = "PQservice / Windows RE hidden Partition / MirOS Partition "
      PType$ = PType$ + "/ RouterBOOT Kernel Partition"
      break
    case 40:
      PType$ = "unused"
      break
    case 41:
      PType$ = "unused"
      break
    case 42:
      PType$ = "AtheOS File System (AFS)"
      break
    case 43:
      PType$ = "SyllableSecure (SylStor)"
      break
    case 44:
      PType$ = "unused"
      break
    case 45:
      PType$ = "unused"
      break
    case 46:
      PType$ = "unused"
      break
    case 47:
      PType$ = "unused"
      break
    case 48:
      PType$ = "unused"
      break
    case 49:
      PType$ = "reserved"
      break
    case 50:
      PType$ = "NOS"
      break
    case 51:
      PType$ = "reserved"
      break
    case 52:
      PType$ = "reserved"
      break
    case 53:
      PType$ = "JFS on OS/2 or eCS"
      break
    case 54:
      PType$ = "reserved"
      break
    case 55:
      PType$ = "unused"
      break
    case 56:
      PType$ = "THEOS Ver. 3.2 2gb Partition"
      break
    case 57:
      PType$ = "Plan 9 Partition / THEOS Ver. 4 spanned Partition"
      break
    case 58:
      PType$ = "THEOS Ver. 4 4gb Partition"
      break
    case 59:
      PType$ = "THEOS Ver. 4 extended Partition"
      break
    case 60:
      PType$ = "Partition Magic recovery Partition"
      break
    case 61:
      PType$ = "Hidden NetWare"
      break
    case 62:
      PType$ = "unused"
      break
    case 63:
      PType$ = "unused"
      break
    case 64:
      PType$ = "Venix 80286 / PICK"
      break
    case 65:
      PType$ = "Linux / MINIX (sharing disk with DRDOS) / Personal RISC "
      PType$ = PType$ + "Boot / PPC PReP (Power PC Reference Platform) Boot"
      break
    case 66:
      PType$ = "Linux Swap (sharing disk with DRDOS / SFS (Secure "
      PType$ = PType$ + "Filesystem) / Windows 2000 dynamic extended "
      PType$ = PType$ + "Partition marker"
      break
    case 67:
      PType$ = "Linux native (sharing disk with DRDOS)"
      break
    case 68:
      PType$ = "GoBack Partition"
      break
    case 69:
      PType$ = "Boot- US boot manager / Priam / EUMEL/Elan"
      break
    case 70:
      PType$ = "EUMEL/Elan"
      break
    case 71:
      PType$ = "EUMEL/Elan"
      break
    case 72:
      PType$ = "EUMEL/Elan"
      break
    case 73:
      PType$ = "unused"
      break
    case 74:
      PType$ = "Mark Aitchison's ALFS/THIN lightweight filesystem for "
      PTyoe$ = PType$ + "DOS / AdaOS Aquila (Withdrawn)"
      break
    case 75:
      PType$ = "unused"
      break
    case 76:
      PType$ = "Oberon partition"
      break
    case 77:
      PType$ = "QNX 4.x"
      break
    case 78:
      PType$ = "QNX 4.x 2nd part"
      break
    case 79:
      PType$ = "QNX 4.x 3rd part / Oberon partition"
      break
    case 80:
      PType$ = "OnTrack Disk Manager (older version) RO / Lynx RTOS / "
      PType$ = PType$ + "Native Oberon (alt)"
      break
    case 81:
      PType$ = "OnTrack Disk Manager / Novell"
      break
    case 82:
      PType$ = "CP/M / Microport SysV/AT"
      break
    case 83:
      PType$ = "Disk Manager 6.0 Aux3"
      break
    case 84:
      PType$ = "Disk manager 6.0 Dynamic Drive Overlay (DDO)"
      break
    case 85:
      PType$ = "EZ- Drive"
      break
    case 86:
      PType$ = "Golden Bow VFeature Partitioned Volume / DM converted to "
      PType$ = PType$ + "EZ- BIOS / AT&T MS- DOS 3.x logically sectored FAT"
      break
    case 87:
      PType$ = "DrivePro / VNDI Partition"
      break
    case 88:
      PType$ = "unused"
      break
    case 89:
      PType$ = "unused"
      break
    case 90:
      PType$ = "unused"
      break
    case 91:
      PType$ = "unused"
      break
    case 92:
      PType$ = "Priam EDisk"
      break
    case 93:
      PType$ = "unused"
      break
    case 94:
      PType$ = "unused"
      break
    case 95:
      PType$ = "unused"
      break
    case 96:
      PType$ = "unused"
      break
    case 97:
      PType$ = "SpeedStor"
      break
    case 98:
      PType$ = "unused"
      break
    case 99:
      PType$ = "Unix System V (SCO, ISC Unix, UnixWare, ...), Mach, GNU Hurd"
      break
    case 100:
      PType$ = "PC- ARMOUR protected partition / Novell Netware 286, 2.xx"
      break
    case 101:
      PType$ = "Novell Netware 386, 3.xx or 4.xx"
      break
    case 102:
      PType$ = "Novell Netware SMS Partition"
      break
    case 103:
      PType$ = "Novell"
      break
    case 104:
      PType$ = "Novell"
      break
    case 105:
      PType$ = "Novell Netware 5+, Novell Netware NSS Partition"
      break
    case 106:
      PType$ = "unused"
      break
    case 107:
      PType$ = "unused"
      break
    case 108:
      PType$ = "unused"
      break
    case 109:
      PType$ = "unused"
      break
    case 110:
      PType$ = "unused"
      break
    case 111:
      PType$ = "unused"
      break
    case 112:
      PType$ = "DiskSecure Multi- Boot"
      break
    case 113:
      PType$ = "reserved"
      break
    case 114:
      PType$ = "V7/x86"
      break
    case 115:
      PType$ = "reserved"
      break
    case 116:
      PType$ = "reserved / Scramdisk partition"
      break
    case 117:
      PType$ = "IBM PC/IX"
      break
    case 118:
      PType$ = "reserved"
      break
    case 119:
      PType$ = "M2FS/M2CS partition / VNDI Partition"
      break
    case 120:
      PType$ = "XOSL FS"
      break
    case 121:
      PType$ = "unused"
      break
    case 122:
      PType$ = "unused"
      break
    case 123:
      PType$ = "unused"
      break
    case 124:
      PType$ = "unused"
      break
    case 125:
      PType$ = "unused"
      break
    case 126:
      PType$ = "unused"
      break
    case 127:
      PType$ = "unused"
      break
    case 128:
      PType$ = "MINIX until 1.4a"
      break
    case 129:
      PType$ = "MINIX since 1.4b, early Linux / Mitac disk manager"
      break
    case 130:
      PType$ = "Prime / Solaris x86 / Linux swap"
      break
    case 131:
      PType$ = "Linux native partition"
      break
    case 132:
      PType$ = "OS/2 hidden C: drive / Hibernation partition"
      break
    case 133:
      PType$ = "Linux extended partition"
      break
    case 134:
      PType$ = "Old Linux RAID partition superblock / FAT16 volume set"
      break
    case 135:
      PType$ = "NTFS volume set"
      break
    case 136:
      PType$ = "Linux plaintext partition table"
      break
    case 137:
      PType$ = "unused"
      break
    case 138:
      PType$ = "Linux Kernel Partition (used by AiR- BOOT)"
      break
    case 139:
      PType$ = "Legacy Fault Tolerant FAT32 volume"
      break
    case 140:
      PType$ = "Legacy Fault Tolerant FAT32 volume using BIOS extd INT 13h"
      break
    case 141:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS FAT12 partition"
      break
    case 142:
      PType$ = "Linux Logical Volume Manager partition"
      break
    case 143:
      PType$ = "unused"
      break
    case 144:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS FAT16 partition"
      break
    case 145:
      PType$ = "Free FDISK 0.96+ hidden DOS extended partition"
      break
    case 146:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS large FAT16 partition"
      break
    case 147:
      PType$ = "Hidden Linux native partition / Amoeba"
      break
    case 148:
      PType$ = "Amoeba bad block table"
      break
    case 149:
      PType$ = "MIT EXOPC native partition"
      break
    case 150:
      PType$ = "CHRP ISO- 9660 filesystem"
      break
    case 151:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS FAT32 partition"
      break
    case 152:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS FAT32 partition (LBA) / "
      PType$ = PType$ + "Datalight ROM- DOS Super- Block Partition"
      break
    case 153:
      PType$ = "DCE376 logical drive"
      break
    case 154:
      PType$ = "Free FDISK 0.96+ hidden Primary DOS FAT16 partition (LBA)"
      break
    case 155:
      PType$ = "Free FDISK 0.96+ hidden DOS extended partition (LBA)"
      break
    case 156:
      PType$ = "unused"
      break
    case 157:
      PType$ = "unused"
      break
    case 158:
      PType$ = "ForthOS partition"
      break
    case 159:
      PType$ = "BSD/OS"
      break
    case 160:
      PType$ = "Laptop hibernation partition"
      break
    case 161:
      PType$ = "Laptop hibernation partition / HP Volume Expansion (SpeedStor"
      PType$ = PType$ + " variant)"
      break
    case 162:
      PType$ = "unused"
      break
    case 163:
      PType$ = "HP Volume Expansion (SpeedStor variant)"
      break
    case 164:
      PType$ = "HP Volume Expansion (SpeedStor variant)"
      break
    case 165:
      PType$ = "BSD/386, 386BSD, NetBSD, FreeBSD"
      break
    case 166:
      PType$ = "OpenBSD / HP Volume Expansion (SpeedStor variant)"
      break
    case 167:
      PType$ = "NeXTStep"
      break
    case 168:
      PType$ = "Mac OS- X"
      break
    case 169:
      PType$ = "NetBSD"
      break
    case 170:
      PType$ = "Olivetti Fat 12 1.44MB Service Partition"
      break
    case 171:
      PType$ = "Mac OS- X Boot partition / GO! partition"
      break
    case 172:
      PType$ = "unused"
      break
    case 173:
      PType$ = "unused"
      break
    case 174:
      PType$ = "ShagOS filesystem"
      break
    case 175:
      PType$ = "ShagOS swap partition / MacOS X HFS"
      break
    case 176:
      PType$ = "BootStar Dummy"
      break
    case 177:
      PType$ = "HP Volume Expansion (SpeedStor variant) / QNX Neutrino "
      PType$ = PType$ + "Power- Safe filesystem"
      break
    case 178:
      PType$ = "QNX Neutrino Power- Safe filesystem"
      break
    case 179:
      PType$ = "HP Volume Expansion (SpeedStor variant) / QNX Neutrino "
      PType$ = PType$ + "Power- Safe filesystem"
      break
    case 180:
      PType$ = "HP Volume Expansion (SpeedStor variant)"
      break
    case 181:
      PType$ = "unused"
      break
    case 182:
      PType$ = "HP Volume Expansion (SpeedStor variant) / Corrupted Windows"
      PType$ = PType$ + " NT mirror set (master), FAT16 file system"
      break
    case 183:
      PType$ = "Corrupted Windows NT mirror set (master), NTFS file system "
      PType$ = PType$ + "/ BSDI BSD/386 filesystem"
      break
    case 184:
      PType$ = "BSDI BSD/386 swap partition"
      break
    case 185:
      PType$ = "unused"
      break
    case 186:
      PType$ = "unused"
      break
    case 187:
      PType$ = "Boot Wizard hidden"
      break
    case 188:
      PType$ = "Acronis backup partition"
      break
    case 189:
      PType$ = "BonnyDOS/286"
      break
    case 190:
      PType$ = "Solaris 8 boot partition"
      break
    case 191:
      PType$ = "New Solaris x86 partition"
      break
    case 192:
      PType$ = "CTOS / REAL/32 secure small partition / NTFT Partition / "
      PType$ = PType$ + "DR- DOS/Novell DOS secured partition"
      break
    case 193:
      PType$ = "DR-DOS/secured (FAT12)"
      break
    case 194:
      PType$ = "Hidden Linux"
      break
    case 195:
      PType$ = "Hidden Linux swap"
      break
    case 196:
      PType$ = "DR-DOS/secured (FAT16, <32M)"
      break
    case 197:
      PType$ = "DR-DOS/secured (extended)"
      break
    case 198:
      PType$ = "DR-DOS/secured FAT16, >=32M) / Windows NT corrupted FAT16 "
      PType$ = PType$ + "volume/stripe set"
      break
    case 199:
      PType$ = "Windows NT corrupted NTFS volume/stripe set / Syrinx boot"
      break
    case 200:
      PType$ = "reserved fpr DR- DOS 8.0x"
      break
    case 201:
      PType$ = "reserved fpr DR- DOS 8.0x"
      break
    case 202:
      PType$ = "reserved fpr DR- DOS 8.0x"
      break
    case 203:
      PType$ = "DR- DOS 7.04+ secured FAT32 (CHS)"
      break
    case 204:
      PType$ = "DR- DOS 7.04+ secured FAT32 (LBA)"
      break
    case 205:
      PType$ = "CTOS Memdump"
      break
    case 206:
      PType$ = "DR- DOS 7.04+ FAT16 (LBA)"
      break
    case 207:
      PType$ = "DR- DOS 7.04+ secured EXT DOS (LBA)"
      break
    case 208:
      PType$ = "REAL/32 secure big partition / Mutiuser DOS secured partition"
      break
    case 209:
      PType$ = "Old Multiuser DOS secured FAT12"
      break
    case 210:
      PType$ = "unused"
      break
    case 211:
      PType$ = "unused"
      break
    case 212:
      PType$ = "Old Multiuser DOS secured FAT16 < 32M"
      break
    case 213:
      PType$ = "Old Multiuser DOS secured extended partition"
      break
    case 214:
      PType$ = "Old Multiuser DOS secured FAT16 >= 32M"
      break
    case 215:
      PType$ = "unused"
      break
    case 216:
      PType$ = "CP/M- 86"
      break
    case 217:
      PType$ = "unused"
      break
    case 218:
      PType$ = "Non- FS Data / Powercopy Backup"
      break
    case 219:
      PType$ = "Digital Research CP/M, Concurrent CP/M, Concurrent DOS / CTOS "
      PType$ = PType$ + "(Convergent Technologies OS- Unisys / KDG Telemetry "
      PType$ = PType$ + "SCPU boot"
      break
    case 220:
      PType$ = "unused"
      break
    case 221:
      PType$ = "Hidden CTOS Memdump"
      break
    case 222:
      PType$ = "Dell PowerEdge Server utilities (FAT fs)"
      break
    case 223:
      PType$ = "DG/UX virtual disk manager partition / BootIt EMBRM"
      break
    case 224:
      PType$ = "reserved by STMicroelectronics for a filesystem called ST AVFS"
      break
    case 225:
      PType$ = "DOS access or SpeedStor 12- bit FAT extended partition"
      break
    case 226:
      PType$ = "unused"
      break
    case 227:
      PType$ = "DOS R/O or SpeedStor"
      break
    case 228:
      PType$ = "SpeedStor 16- bit FAT extended partition < 1024 cyl."
      break
    case 229:
      PType$ = "Tandy MS- DOS with logically sectored FAT"
      break
    case 230:
      PType$ = "Storage Dimensions SpeedStor"
      break
    case 231:
      PType$ = "unused"
      break
    case 232:
      PType$ = "LUKS"
      break
    case 233:
      PType$ = "unused"
      break
    case 234:
      PType$ = "unused"
      break
    case 235:
      PType$ = "BeOS BFS"
      break
    case 236:
      PType$ = "SkyOS SkyFS"
      break
    case 237:
      PType$ = "unused"
      break
    case 238:
      PType$ = "Indication that this legacy MBR is followed by an EFI"
      PType$ = PType$ + " header"
      break
    case 239:
      PType$ = "Partition that contains an EFI file system"
      break
    case 240:
      PType$ = "Linux/PA- RISC boot loader"
      break
    case 241:
      PType$ = "Storage Dimensions SpeedStor"
      break
    case 242:
      PType$ = "DOS 3.3+ secondary partition"
      break
    case 243:
      PType$ = "reserved"
      break
    case 244:
      PType$ = "SpeedStor large partition / Prologue single- volume partition"
      break
    case 245:
      PType$ = "Prologue multi- volume partition"
      break
    case 246:
      PType$ = "Storage Dimensions SpeedStor"
      break
    case 247:
      PType$ = "DDRdrive Solid State File System"
      break
    case 248:
      PType$ = "unused"
      break
    case 249:
      PType$ = "pCache"
      break
    case 250:
      PType$ = "Bochs"
      break
    case 251:
      PType$ = "VMware File System partition"
      break
    case 252:
      PType$ = "VMware Swap partition"
      break
    case 253:
      PType$ = "Linux RAID partition with autodetect using persistent superblock"
      break
    case 254:
      PType$ = "SpeedStor > 1024 cyl. / LANstep / IBM PS/2 IML (Initial Microcode"
      PType$ = PType$ + " Load) partition, located at the end of the disk / "
      PType$ = PType$ + "Windows NT Disk Administrator hidden partition / Linux "
      PType$ = PType$ + "Logical Volume Manager partition (old)"
      break
    case 255:
      PType$ = "XENIX Bad Block Table"
      break
    
  end switch
  
  // Partitions- Typ zurückgeben
  return PType$
    
end sub


(getestet mit Haiku R1 Alpha 3 und yab 1.5)

Keine Kommentare:

Kommentar veröffentlichen