/Kernel/Source/Hardware/SystemPartition.c

https://github.com/Astaelan/SEMOS · C · 311 lines · 276 code · 33 blank · 2 comment · 61 complexity · b4a96b5602fbdeb2fe06bcc327090948 MD5 · raw file

  1. #include <errno.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <PortIO.h>
  6. #include <FileSystem.h>
  7. #include <Hardware/SystemPartition.h>
  8. #include <Hardware/IDT.h>
  9. #include <Hardware/VGAText.h>
  10. #include <Hardware/ATA/ATADevice.h>
  11. #include <Hardware/ATA/ATAPIDevice.h>
  12. #include <Utility/List.h>
  13. #undef errno
  14. extern int errno;
  15. char * strdup(const char *);
  16. int strcasecmp(const char *, const char *);
  17. typedef struct
  18. {
  19. BYTE EntrySize;
  20. UINT32 LBA;
  21. UINT32 Length;
  22. BYTE Flags;
  23. PSTRING Identifier;
  24. List Entries;
  25. } SystemPartitionCache;
  26. BOOL SystemPartition_Detect();
  27. BOOL SystemPartition_DetectATA(UINT16 pBaseAddress);
  28. BOOL SystemPartition_DetectATAPIISO9660(ATADevice * pDevice);
  29. BOOL SystemPartition_DetectATAPIISO9660SystemPartition(ATADevice * pDevice, UINT32 * pDescriptorSector);
  30. void SystemPartition_Cache(SystemPartitionCache * pCache);
  31. INT32 SystemPartition_OpenHandler(FileDescriptor * pDescriptor, const char * pPath, INT32 pFlags, mode_t pMode);
  32. INT32 SystemPartition_CloseHandler(FileDescriptor * pDescriptor);
  33. off_t SystemPartition_LSeekHandler(FileDescriptor * pDescriptor, off_t pOffset, INT32 pWhence);
  34. INT32 SystemPartition_WriteHandler(FileDescriptor * pDescriptor, const void * pData, size_t pLength);
  35. INT32 SystemPartition_ReadHandler(FileDescriptor * pDescriptor, void * pData, size_t pLength);
  36. ATADevice * gSystemPartitionDevice = NULL;
  37. UINT32 gSystemPartitionDescriptorSector = 0;
  38. SystemPartitionCache gSystemPartitionCache;
  39. void SystemPartition_Initialize()
  40. {
  41. if(!SystemPartition_Detect()) return;
  42. PSTRING rootMount = "/SYSTEM";
  43. UINT32 rootMountLength = strlen(rootMount);
  44. PBYTE sectorBuffer = (PBYTE)malloc(ATAPIDEVICE_IO_SECTOR_SIZE);
  45. ATAPIDevice_ReadSector(gSystemPartitionDevice, gSystemPartitionDescriptorSector, sectorBuffer);
  46. gSystemPartitionCache.EntrySize = *(sectorBuffer + 156);
  47. gSystemPartitionCache.LBA = *(UINT32 *)(sectorBuffer + 156 + 2);
  48. gSystemPartitionCache.Length = *(UINT32 *)(sectorBuffer + 156 + 10);
  49. gSystemPartitionCache.Flags = *(sectorBuffer + 156 + 25);
  50. gSystemPartitionCache.Identifier = (PSTRING)malloc(rootMountLength + 1);
  51. strncpy(gSystemPartitionCache.Identifier, rootMount, rootMountLength);
  52. gSystemPartitionCache.Identifier[rootMountLength] = 0x00;
  53. free(sectorBuffer);
  54. SystemPartition_Cache(&gSystemPartitionCache);
  55. FileSystem_Register(rootMount, &SystemPartition_OpenHandler);
  56. }
  57. BOOL SystemPartition_Detect()
  58. {
  59. BOOL hasDisk = SystemPartition_DetectATA(ATADEVICE_IO_PRIMARY_BASE);
  60. if (hasDisk)
  61. {
  62. ATADevice * master = ATADevice_Initialize(ATADEVICE_IO_PRIMARY_BASE, ATADEVICE_IO_PRIMARY_CONTROL, ATADEVICE_IRQ_PRIMARY, FALSE);
  63. UINT32 descriptorSector = 0;
  64. if (master->Type == ATADEVICE_TYPE_PATAPI &&
  65. SystemPartition_DetectATAPIISO9660(master) &&
  66. SystemPartition_DetectATAPIISO9660SystemPartition(master, &descriptorSector))
  67. {
  68. gSystemPartitionDevice = master;
  69. gSystemPartitionDescriptorSector = descriptorSector;
  70. return TRUE;
  71. }
  72. free(master);
  73. ATADevice * slave = ATADevice_Initialize(ATADEVICE_IO_PRIMARY_BASE, ATADEVICE_IO_PRIMARY_CONTROL, ATADEVICE_IRQ_PRIMARY, TRUE);
  74. if (slave->Type == ATADEVICE_TYPE_PATAPI &&
  75. SystemPartition_DetectATAPIISO9660(slave) &&
  76. SystemPartition_DetectATAPIISO9660SystemPartition(slave, &descriptorSector))
  77. {
  78. gSystemPartitionDevice = slave;
  79. gSystemPartitionDescriptorSector = descriptorSector;
  80. return TRUE;
  81. }
  82. free(slave);
  83. }
  84. hasDisk = SystemPartition_DetectATA(ATADEVICE_IO_SECONDARY_BASE);
  85. if (hasDisk)
  86. {
  87. ATADevice * master = ATADevice_Initialize(ATADEVICE_IO_SECONDARY_BASE, ATADEVICE_IO_SECONDARY_CONTROL, ATADEVICE_IRQ_SECONDARY, FALSE);
  88. UINT32 descriptorSector = 0;
  89. if (master->Type == ATADEVICE_TYPE_PATAPI &&
  90. SystemPartition_DetectATAPIISO9660(master) &&
  91. SystemPartition_DetectATAPIISO9660SystemPartition(master, &descriptorSector))
  92. {
  93. gSystemPartitionDevice = master;
  94. gSystemPartitionDescriptorSector = descriptorSector;
  95. return TRUE;
  96. }
  97. free(master);
  98. ATADevice * slave = ATADevice_Initialize(ATADEVICE_IO_SECONDARY_BASE, ATADEVICE_IO_SECONDARY_CONTROL, ATADEVICE_IRQ_SECONDARY, TRUE);
  99. if (slave->Type == ATADEVICE_TYPE_PATAPI &&
  100. SystemPartition_DetectATAPIISO9660(slave) &&
  101. SystemPartition_DetectATAPIISO9660SystemPartition(slave, &descriptorSector))
  102. {
  103. gSystemPartitionDevice = slave;
  104. gSystemPartitionDescriptorSector = descriptorSector;
  105. return TRUE;
  106. }
  107. free(slave);
  108. }
  109. return FALSE;
  110. }
  111. BOOL SystemPartition_DetectATA(UINT16 pBaseAddress)
  112. {
  113. outb(pBaseAddress + ATADEVICE_IO_SECTORS, 0xDE);
  114. outb(pBaseAddress + ATADEVICE_IO_ADDRESS0, 0xAD);
  115. return inb(pBaseAddress + ATADEVICE_IO_SECTORS) == 0xDE && inb(pBaseAddress + ATADEVICE_IO_ADDRESS0) == 0xAD;
  116. }
  117. BOOL SystemPartition_DetectATAPIISO9660(ATADevice * pDevice)
  118. {
  119. BYTE sectorBuffer[ATAPIDEVICE_IO_SECTOR_SIZE];
  120. UINT32 bytesRead = ATAPIDevice_ReadSector(pDevice, 0x10, sectorBuffer);
  121. if (bytesRead < 6) return FALSE;
  122. return sectorBuffer[1] == 'C' && sectorBuffer[2] == 'D' && sectorBuffer[3] == '0' && sectorBuffer[4] == '0' && sectorBuffer[5] == '1';
  123. }
  124. BOOL SystemPartition_DetectATAPIISO9660SystemPartition(ATADevice * pDevice,
  125. UINT32 * pDescriptorSector)
  126. {
  127. UINT32 sector = 0x10;
  128. BYTE sectorBuffer[ATAPIDEVICE_IO_SECTOR_SIZE];
  129. while (ATAPIDevice_ReadSector(pDevice, sector, sectorBuffer) > 0)
  130. {
  131. ++sector;
  132. if (sectorBuffer[0] == 0xFF) break;
  133. if (sectorBuffer[0] != 0x01) continue;
  134. if (sectorBuffer[40] == 'S' &&
  135. sectorBuffer[41] == 'E' &&
  136. sectorBuffer[42] == 'M' &&
  137. sectorBuffer[43] == 'O' &&
  138. sectorBuffer[44] == 'S') { *pDescriptorSector = sector - 1; return TRUE; }
  139. }
  140. return FALSE;
  141. }
  142. void SystemPartition_Cache(SystemPartitionCache * pCache)
  143. {
  144. PBYTE sectorBuffer = (PBYTE)malloc(ATAPIDEVICE_IO_SECTOR_SIZE);
  145. PBYTE sectorBuf = sectorBuffer;
  146. ATAPIDevice_ReadSector(gSystemPartitionDevice, pCache->LBA, sectorBuffer);
  147. BYTE entrySize = *sectorBuf;
  148. sectorBuf += entrySize;
  149. entrySize = *sectorBuf;
  150. sectorBuf += entrySize;
  151. BYTE parentIdentifierLength = strlen(pCache->Identifier);
  152. entrySize = *sectorBuf;
  153. while (entrySize != 0)
  154. {
  155. SystemPartitionCache * cache = (SystemPartitionCache *)malloc(sizeof(SystemPartitionCache));
  156. cache->EntrySize = entrySize;
  157. cache->LBA = *(UINT32 *)(sectorBuf + 2);
  158. cache->Length = *(UINT32 *)(sectorBuf + 10);
  159. cache->Flags = *(sectorBuf + 25);
  160. BYTE identifierLength = *(sectorBuf + 32);
  161. if (!(cache->Flags & 0x02)) identifierLength -= 2;
  162. cache->Identifier = (PSTRING)malloc(parentIdentifierLength + 1 + identifierLength + 1);
  163. strncpy(cache->Identifier, pCache->Identifier, parentIdentifierLength);
  164. cache->Identifier[parentIdentifierLength] = '/';
  165. strncpy(cache->Identifier + parentIdentifierLength + 1, (PSTRING)(sectorBuf + 33), identifierLength);
  166. cache->Identifier[parentIdentifierLength + 1 + identifierLength] = 0x00;
  167. cache->Entries.Head = NULL;
  168. cache->Entries.Tail = NULL;
  169. cache->Entries.Count = 0;
  170. List_Add(&pCache->Entries, cache);
  171. //printf("%s, LBA = 0x%x, Length = 0x%x, Flags = 0x%x\n", cache->Identifier, cache->LBA, cache->Length, cache->Flags);
  172. if (cache->Flags & 0x02) SystemPartition_Cache(cache);
  173. sectorBuf += entrySize;
  174. entrySize = *sectorBuf;
  175. }
  176. free(sectorBuffer);
  177. }
  178. SystemPartitionCache * SystemPartition_FindCached(SystemPartitionCache * pCache, const char * pPath)
  179. {
  180. if (!strcasecmp(pCache->Identifier, pPath)) return pCache;
  181. for (Node * node = pCache->Entries.Head; node; node = node->Next)
  182. {
  183. SystemPartitionCache * cache = (SystemPartitionCache *)node->Data;
  184. cache = SystemPartition_FindCached(cache, pPath);
  185. if (cache) return cache;
  186. }
  187. return NULL;
  188. }
  189. INT32 SystemPartition_OpenHandler(FileDescriptor * pDescriptor, const char * pPath, INT32 pFlags, mode_t pMode)
  190. {
  191. SystemPartitionCache * cache = SystemPartition_FindCached(&gSystemPartitionCache, pPath);
  192. if (!cache)
  193. {
  194. errno = EACCES;
  195. return -1;
  196. }
  197. printf("Opening %s, %d bytes...\n", cache->Identifier, cache->Length);
  198. if (pFlags && pMode) { }
  199. pDescriptor->Active = TRUE;
  200. pDescriptor->BlockStart = cache->LBA;
  201. pDescriptor->Mode = S_IFBLK | (S_IREAD >> 3) | (S_IREAD >> 6);
  202. pDescriptor->TotalSize = cache->Length;
  203. pDescriptor->BlockSize = ATAPIDEVICE_IO_SECTOR_SIZE;
  204. pDescriptor->BlockCount = pDescriptor->TotalSize / pDescriptor->BlockSize;
  205. if ((pDescriptor->TotalSize % pDescriptor->BlockSize) != 0) ++pDescriptor->BlockCount;
  206. pDescriptor->Path = strdup(cache->Identifier);
  207. pDescriptor->CloseHandler = &SystemPartition_CloseHandler;
  208. pDescriptor->LSeekHandler = &SystemPartition_LSeekHandler;
  209. pDescriptor->WriteHandler = &SystemPartition_WriteHandler;
  210. pDescriptor->ReadHandler = &SystemPartition_ReadHandler;
  211. return pDescriptor->Index;
  212. }
  213. INT32 SystemPartition_CloseHandler(FileDescriptor * pDescriptor)
  214. {
  215. pDescriptor->Active = FALSE;
  216. pDescriptor->Device = 0;
  217. pDescriptor->BlockStart = 0;
  218. pDescriptor->Mode = 0;
  219. pDescriptor->TotalSize = 0;
  220. pDescriptor->BlockSize = 0;
  221. pDescriptor->BlockCount = 0;
  222. pDescriptor->TerminalStream = FALSE;
  223. pDescriptor->Offset = 0;
  224. free(pDescriptor->Path);
  225. pDescriptor->Path = NULL;
  226. pDescriptor->CloseHandler = NULL;
  227. pDescriptor->LSeekHandler = NULL;
  228. pDescriptor->WriteHandler = NULL;
  229. pDescriptor->ReadHandler = NULL;
  230. return 0;
  231. }
  232. off_t SystemPartition_LSeekHandler(FileDescriptor * pDescriptor, off_t pOffset, INT32 pWhence)
  233. {
  234. off_t tempOffset = pDescriptor->Offset;
  235. switch (pWhence)
  236. {
  237. case SEEK_SET: tempOffset = pOffset; break;
  238. case SEEK_CUR: tempOffset += pOffset; break;
  239. case SEEK_END: tempOffset = pDescriptor->TotalSize; break;
  240. default:
  241. errno = EINVAL;
  242. return -1;
  243. }
  244. if (tempOffset <= 0) pDescriptor->Offset = 0;
  245. else if ((UINT32)tempOffset >= pDescriptor->TotalSize) pDescriptor->Offset = pDescriptor->TotalSize;
  246. else pDescriptor->Offset = tempOffset;
  247. //printf("SystemPartition LSeekHandler: %i, %i = %u\n", (INT32)pOffset, pWhence, pDescriptor->Offset);
  248. return (off_t)pDescriptor->Offset;
  249. }
  250. INT32 SystemPartition_WriteHandler(FileDescriptor * pDescriptor, const void * pData, size_t pLength)
  251. {
  252. if (pDescriptor && pData && pLength) { }
  253. errno = EBADF;
  254. return -1;
  255. }
  256. INT32 SystemPartition_ReadHandler(FileDescriptor * pDescriptor, void * pData, size_t pLength)
  257. {
  258. PBYTE sectorBuffer = (PBYTE)malloc(ATAPIDEVICE_IO_SECTOR_SIZE);
  259. UINT32 dataOffset = 0;
  260. UINT32 dataRemaining = pLength;
  261. UINT32 currentBlock = pDescriptor->BlockStart + (pDescriptor->Offset / ATAPIDEVICE_IO_SECTOR_SIZE);
  262. while (pDescriptor->Offset < pDescriptor->TotalSize && dataRemaining > 0)
  263. {
  264. UINT32 sectorLength = ATAPIDevice_ReadSector(gSystemPartitionDevice, currentBlock, sectorBuffer);
  265. UINT32 sectorOffset = pDescriptor->Offset % ATAPIDEVICE_IO_SECTOR_SIZE;
  266. UINT32 sectorUsable = sectorLength - sectorOffset;
  267. UINT32 sectorConsumed = dataRemaining;
  268. if (sectorConsumed > sectorUsable) sectorConsumed = sectorUsable;
  269. if ((pDescriptor->Offset + sectorConsumed) > pDescriptor->TotalSize) sectorConsumed = pDescriptor->TotalSize - pDescriptor->Offset;
  270. memcpy(pData + dataOffset, sectorBuffer + sectorOffset, sectorConsumed);
  271. pDescriptor->Offset += sectorConsumed;
  272. dataOffset += sectorConsumed;
  273. dataRemaining -= sectorConsumed;
  274. if (pDescriptor->Offset < pDescriptor->TotalSize && dataRemaining > 0) ++currentBlock;
  275. }
  276. free(sectorBuffer);
  277. return dataOffset;
  278. }