1 00:00:01,020 --> 00:00:06,330 In this lecture we are going to write a console where we can issue a command and get the result from kernel. 2 00:00:06,330 --> 00:00:08,960 The command we support in this example 3 00:00:08,980 --> 00:00:13,050 is get total memory. Let’s get started. 4 00:00:14,220 --> 00:00:16,129 The console is running in the user mode. 5 00:00:16,320 --> 00:00:20,940 So what we are going to do is we are going to implement it in the user2 program 6 00:00:26,640 --> 00:00:29,960 As you see, I have added the code in the main.c file. 7 00:00:30,980 --> 00:00:32,930 We start off with main function. 8 00:00:35,110 --> 00:00:42,370 The variable buffer is used to save the data we send with keyboard. The buffer size specifies how many characters we get in the console 9 00:00:42,370 --> 00:00:45,070 before we issue a command. 10 00:00:45,850 --> 00:00:49,920 Each time we press enter, the buffer size is reset to 0. 11 00:00:50,910 --> 00:00:53,970 The cmd is the index of the commands we support. 12 00:00:54,930 --> 00:01:00,480 Then we get to the infinite loop where we receive the data, issue a command and print the result on the screen 13 00:01:00,480 --> 00:01:01,080 . 14 00:01:02,440 --> 00:01:08,380 The layout of the screen is like this, at the beginning of each line, we have the command prompt shell and hash tag. 15 00:01:08,620 --> 00:01:11,790 Then we can type the command we want to execute, 16 00:01:11,800 --> 00:01:15,250 and press enter to issue the command. 17 00:01:16,700 --> 00:01:23,300 Ok, let’s continue. Next we will read the data from the keyboard. When we return from it, 18 00:01:23,300 --> 00:01:24,200 we will check the buffer size, 19 00:01:24,590 --> 00:01:30,080 if the buffer size is 0, then there is no command found. We simply continue the loop. 20 00:01:30,590 --> 00:01:32,360 Otherwise, we will parse the command. 21 00:01:33,600 --> 00:01:38,880 If the return value is negative, then it means that the command is invalid, we print command not found 22 00:01:38,880 --> 00:01:39,420 . 23 00:01:40,480 --> 00:01:46,200 Otherwise, this is a command we support, we execute the command by function execute command. 24 00:01:47,390 --> 00:01:50,420 Ok, let’s see what we have in the function read command. 25 00:01:52,700 --> 00:01:54,950 As you see, we read a key from keyboard. 26 00:01:55,950 --> 00:02:01,890 The else clause deals with normal keys. In this case, we copy the data to the buffer 27 00:02:01,890 --> 00:02:04,650 and update the buffer size, then we print it on the screen. 28 00:02:06,400 --> 00:02:11,590 If it’s an enter key which means we want to issue a command, then we print the enter key, 29 00:02:12,560 --> 00:02:14,960 break the loop and return buffer size. 30 00:02:15,950 --> 00:02:21,710 Here we also check the buffer size, in this example, we will allow the size of a command no more than 80 characters. 31 00:02:21,710 --> 00:02:28,180 So if it’s more than 80, we will view it as a command and return. 32 00:02:29,720 --> 00:02:34,490 Another case we need to handle is when we press backspace key to delete characters. 33 00:02:35,510 --> 00:02:41,210 So here we check the buffer size. If the buffer size is 0, it means that we are at the beginning of the line 34 00:02:41,210 --> 00:02:42,970 and we do nothing. 35 00:02:43,580 --> 00:02:47,360 Otherwise, we decrement the buffer size and print backspace. 36 00:02:48,840 --> 00:02:51,170 Alright, that’s it for read command function. 37 00:02:52,260 --> 00:02:54,870 Now let's move to function parse command. 38 00:02:56,650 --> 00:03:03,730 First off, we define variable command used as an index number. We initialize it with -1 which means this is an invalid index. 39 00:03:03,760 --> 00:03:08,290 Since we only have one command available, 40 00:03:08,590 --> 00:03:14,320 so we check if the size of command is equal to 8 and it’s the totalmem command. 41 00:03:15,010 --> 00:03:19,540 If it’s totalmem, we return the index number 0 in this case. 42 00:03:20,380 --> 00:03:23,020 As for other commands, we simply return -1. 43 00:03:24,210 --> 00:03:30,590 the memcpy function is implemented in the lib.asm file . So we can use the function in that file. 44 00:03:31,500 --> 00:03:37,770 OK, after we get the index number, we can execute the command by the function execute command. 45 00:03:37,770 --> 00:03:39,180 In the header file, 46 00:03:40,740 --> 00:03:42,210 we define the command type. 47 00:03:45,000 --> 00:03:51,310 At this point, we have one command in the list, get total mem. 48 00:03:51,330 --> 00:03:57,570 Therefore, if the index number is 0, we will call get total memory function. In order to retrieve the memory information, 49 00:03:57,570 --> 00:04:01,290 we need to send the request to the kernel. In this function, 50 00:04:01,290 --> 00:04:04,590 we call get memory total u and print the result. a 51 00:04:06,480 --> 00:04:08,190 In the syscall.c file, 52 00:04:10,980 --> 00:04:13,410 we add the sys get total memory function. 53 00:04:14,370 --> 00:04:20,730 And in this function, the only thing we will do is call get total memory function. Remember the total memory is saved 54 00:04:20,730 --> 00:04:22,840 in the memory module. 55 00:04:23,190 --> 00:04:25,200 So we open memory.c file. 56 00:04:29,950 --> 00:04:33,290 As you can see, the variable total memory is defined here. 57 00:04:34,150 --> 00:04:36,520 Now we define it as a global variable. 58 00:04:40,160 --> 00:04:46,840 Also, we add function get total memory where we simply return the total memory in mb format. 59 00:04:49,080 --> 00:04:54,990 Add the declaration in the header file and the kernel part is done. Move to the user part. 60 00:04:56,400 --> 00:04:59,130 We are going to add function in syscall file. 61 00:05:02,100 --> 00:05:07,530 So we define get total memoryu. 62 00:05:10,470 --> 00:05:13,410 The index of get total memory u is 5 63 00:05:16,680 --> 00:05:20,100 and it doesn’t have parameters. We clear rdi register 64 00:05:24,130 --> 00:05:25,620 then we int 80 65 00:05:27,540 --> 00:05:30,590 After we return from kernel, the data is in rax. 66 00:05:32,380 --> 00:05:33,370 and then we return. 67 00:05:34,990 --> 00:05:38,710 Since we used the memcpy function in the main.c file, 68 00:05:39,780 --> 00:05:44,160 we need to copy the lib.asm file into user2 program. 69 00:05:46,040 --> 00:05:49,790 We also need to add the declaration of the functions 70 00:05:50,910 --> 00:05:51,810 into the header file. 71 00:05:57,510 --> 00:05:59,910 OK, now we declare the get total memoryu 72 00:06:03,090 --> 00:06:04,650 and add the declaration here. 73 00:06:08,690 --> 00:06:12,140 OK, let's build the project. We first build the library. 74 00:06:22,710 --> 00:06:23,940 We run the build script. 75 00:06:25,690 --> 00:06:29,710 We copy the binary file into boot folder 76 00:06:35,900 --> 00:06:37,340 and build the kernel project. 77 00:06:39,660 --> 00:06:41,210 OK, let's open the bochs 78 00:06:47,280 --> 00:06:51,050 OK, let's test the command. We type totalmem 79 00:06:52,840 --> 00:06:57,380 And you can see the total memory is 1023mb 80 00:06:58,120 --> 00:07:01,120 This is the memory we allocated for the virtual machine. 81 00:07:02,370 --> 00:07:03,810 As for other commands, 82 00:07:06,680 --> 00:07:08,960 the console simply returns command not found. 83 00:07:10,300 --> 00:07:14,500 And now you know the general process of adding a command to the system. 84 00:07:15,600 --> 00:07:19,260 if you like, you can add more commands to the system yourself. 85 00:07:20,470 --> 00:07:22,360 OK, that's it for this lecture.