Index: lab5/graphics.c
===================================================================
--- lab5/graphics.c	(revision 110)
+++ lab5/graphics.c	(revision 111)
@@ -73,6 +73,18 @@
     return (vbe_mem_info.BitsPerPixel + 7) >> 3;
 }
 
+uint16_t get_RedMaskSize(void){
+    return vbe_mem_info.RedMaskSize;
+}
+
+uint16_t get_GreenMaskSize(void){
+    return vbe_mem_info.GreenMaskSize;
+}
+
+uint16_t get_BlueMaskSize(void){
+    return vbe_mem_info.BlueMaskSize;
+}
+
 int (map_vram)(void) {
     int r;
     unsigned int vram_base = get_phys_addr();
Index: lab5/graphics.h
===================================================================
--- lab5/graphics.h	(revision 110)
+++ lab5/graphics.h	(revision 111)
@@ -22,6 +22,12 @@
 
 uint16_t get_bytes_pixel(void);
 
+uint16_t get_RedMaskSize(void);
+
+uint16_t get_GreenMaskSize(void);
+
+uint16_t get_BlueMaskSize(void);
+
 int (map_vram)(void);
 
 int (free_memory)(void);
Index: lab5/lab5.c
===================================================================
--- lab5/lab5.c	(revision 110)
+++ lab5/lab5.c	(revision 111)
@@ -75,7 +75,8 @@
     return 0;
 }
 
-///lcom_run lab5 "rectangle 105 3 3 30 30 12 -t 1"
+// lcom_run lab5 "rectangle 105 100 100 100 100 1"
+// lcom_run lab5 "rectangle 115 100 100 100 100 FF0000"
 int(video_test_rectangle)(uint16_t mode, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
     int r;
     if ((r = get_permissions_first_mbyte()))
@@ -165,11 +166,105 @@
 }
 
 int(video_test_pattern)(uint16_t mode, uint8_t no_rectangles, uint32_t first, uint8_t step) {
-  /* To be completed */
-  printf("%s(0x%03x, %u, 0x%08x, %d): under construction\n", __func__,
-         mode, no_rectangles, first, step);
+    int r;
+    if ((r = get_permissions_first_mbyte()))
+        panic("%s: sys_privctl (ADD MEM) failed: %d\n", __func__, r);
 
-  return 1;
+    if (vbe_get_mode_information(mode)) {
+        printf("%s: failed to get information for mode %x.\n", __func__, mode);
+        if (vg_exit())
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+        return 1;
+    }
+
+    map_vram(); // if function fails it aborts program
+
+    if (set_graphics_mode(mode)) {
+        printf("%s: failed to set graphic mode %x.\n", __func__, mode);
+        if (vg_exit()) printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+        return 1;
+    }
+    uint16_t W = get_XRes()/no_rectangles;
+    uint16_t H = get_YRes()/no_rectangles;
+    uint32_t color, R, G, B;
+    for(uint8_t row = 0; row < no_rectangles; ++row){
+        for(uint8_t col = 0; col < no_rectangles; ++col){
+            if(mode == 0x105){
+                color = (first + (row * no_rectangles + col) * step) % (1 << get_bits_pixel());
+            }else{
+                R = (first + col*step) % (1 << get_RedMaskSize());
+                G = (first + row*step) % (1 << get_GreenMaskSize());
+                B = (first + (col+row)*step) % (1 << get_BlueMaskSize());
+                color = (R<<16) | (G<<8) | (B);
+            }
+            if (vg_draw_rectangle(col*W,row*H,W,H,color)) {
+                if (vg_exit()) {
+                    printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+                    if (free_memory()) printf("%s: lm_free failed\n", __func__);
+                }
+                return 1;
+            }
+        }
+    }
+
+    /// loop stuff
+    int ipc_status;
+    message msg;
+    /// Keyboard interrupt handling
+    uint8_t kbc_irq_bit = KBC_IRQ;
+    int kbc_id = 0;
+    int kbc_irq = BIT(kbc_irq_bit);
+    if (subscribe_kbc_interrupt(kbc_irq_bit, &kbc_id)) {
+        if (vg_exit()) {
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+            if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        }
+        return 1;
+    }
+    /// cycle
+    int good = 1;
+    while (good) {
+        /* Get a request message. */
+        if ((r = driver_receive(ANY, &msg, &ipc_status)) != 0) {
+            printf("driver_receive failed with %d", r);
+            continue;
+        }
+        if (is_ipc_notify(ipc_status)) { /* received notification */
+            switch (_ENDPOINT_P(msg.m_source)) {
+                case HARDWARE: /* hardware interrupt notification */
+                    if (msg.m_notify.interrupts & kbc_irq) { /* subscribed interrupt */
+                        kbc_ih();
+                        if (scancode[0] == ESC_BREAK_CODE) good = 0;
+                    }
+                    break;
+                default:
+                    break; /* no other notifications expected: do nothing */
+            }
+        } else { /* received standart message, not a notification */
+            /* no standart message expected: do nothing */
+        }
+    }
+
+    if (unsubscribe_interrupt(&kbc_id)) {
+        if (vg_exit()) {
+            printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+            if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        }
+        return 1;
+    };
+
+    if (vg_exit()) {
+        printf("%s: vg_exit failed to exit to text mode.\n", __func__);
+        if (free_memory()) printf("%s: lm_free failed\n", __func__);
+        return 1;
+    }
+
+    if (free_memory()) {
+        printf("%s: lm_free failed\n", __func__);
+        return 1;
+    }
+
+    return 0;
 }
 
 int(video_test_xpm)(xpm_map_t xpm, uint16_t x, uint16_t y) {
